2 * Copyright (c) 1998 Søren Schmidt
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
38 #include <sys/malloc.h>
41 #include <machine/clock.h>
42 #include <i386/isa/atapi.h>
44 static d_open_t wstopen;
45 static d_close_t wstclose;
46 static d_ioctl_t wstioctl;
47 static d_strategy_t wststrategy;
51 static struct cdevsw wst_cdevsw = {
55 /* write */ physwrite,
59 /* strategy */ wststrategy,
68 static unsigned int wst_total = 0;
70 #define NUNIT (NWDC*2)
71 #define UNIT(d) ((minor(d) >> 3) & 3)
73 #define WST_OPEN 0x0001 /* The device is opened */
74 #define WST_MEDIA_CHANGED 0x0002 /* The media have changed */
75 #define WST_DATA_WRITTEN 0x0004 /* Data has been written */
76 #define WST_FM_WRITTEN 0x0008 /* Filemark has been written */
77 #define WST_DEBUG 0x0010 /* Print debug info */
78 #define WST_CTL_WARN 0x0020 /* Have we warned about CTL wrong? */
80 /* ATAPI tape commands not in std ATAPI command set */
81 #define ATAPI_TAPE_REWIND 0x01
82 #define ATAPI_TAPE_REQUEST_SENSE 0x03
83 #define ATAPI_TAPE_READ_CMD 0x08
84 #define ATAPI_TAPE_WRITE_CMD 0x0a
85 #define ATAPI_TAPE_WEOF 0x10
86 #define WEOF_WRITE_MASK 0x01
87 #define ATAPI_TAPE_SPACE_CMD 0x11
90 #define ATAPI_TAPE_ERASE 0x19
91 #define ATAPI_TAPE_MODE_SENSE 0x1a
92 #define ATAPI_TAPE_LOAD_UNLOAD 0x1b
93 #define LU_LOAD_MASK 0x01
94 #define LU_RETENSION_MASK 0x02
95 #define LU_EOT_MASK 0x04
97 #define DSC_POLL_INTERVAL 10
100 * MODE SENSE parameter header
103 u_char data_length; /* Total length of data */
104 u_char medium_type; /* Medium type (if any) */
105 u_char dsp; /* Device specific parameter */
106 u_char bdl; /* Block Descriptor Length */
110 * ATAPI tape drive Capabilities and Mechanical Status Page
112 #define ATAPI_TAPE_CAP_PAGE 0x2a
115 u_int page_code :6; /* Page code == 0x2a */
116 u_int reserved1_67 :2;
117 u_char page_length; /* Page Length == 0x12 */
120 u_int readonly :1; /* Read Only Mode */
121 u_int reserved4_1234 :4;
122 u_int reverse :1; /* Supports reverse direction */
123 u_int reserved4_67 :2;
124 u_int reserved5_012 :3;
125 u_int eformat :1; /* Supports ERASE formatting */
126 u_int reserved5_4 :1;
127 u_int qfa :1; /* Supports QFA formats */
128 u_int reserved5_67 :2;
129 u_int lock :1; /* Supports locking media */
130 u_int locked :1; /* The media is locked */
131 u_int prevent :1; /* Defaults to prevent state */
132 u_int eject :1; /* Supports eject */
133 u_int disconnect :1; /* Can break request > ctl */
134 u_int reserved6_5 :1;
135 u_int ecc :1; /* Supports error correction */
136 u_int compress :1; /* Supports data compression */
137 u_int reserved7_0 :1;
138 u_int blk512 :1; /* Supports 512b block size */
139 u_int blk1024 :1; /* Supports 1024b block size */
140 u_int reserved7_3456 :4;
141 u_int slowb :1; /* Restricts byte count */
142 u_short max_speed; /* Supported speed in KBps */
143 u_short max_defects; /* Max stored defect entries */
144 u_short ctl; /* Continuous Transfer Limit */
145 u_short speed; /* Current Speed, in KBps */
146 u_short buffer_size; /* Buffer Size, in 512 bytes */
152 * REQUEST SENSE structure
154 struct wst_reqsense {
155 u_int error_code :7; /* Current or deferred errors */
156 u_int valid :1; /* Follows QIC-157C */
157 u_char reserved1; /* Segment Number - Reserved */
158 u_int sense_key :4; /* Sense Key */
159 u_int reserved2_4 :1; /* Reserved */
160 u_int ili :1; /* Incorrect Length Indicator */
161 u_int eom :1; /* End Of Medium */
162 u_int filemark :1; /* Filemark */
163 u_int info __attribute__((packed)); /* Cmd specific info */
164 u_char asl; /* Additional sense length (n-7) */
165 u_int command_specific; /* Additional cmd specific info */
166 u_char asc; /* Additional Sense Code */
167 u_char ascq; /* Additional Sense Code Qualifier */
168 u_char replaceable_unit_code; /* Field Replaceable Unit Code */
169 u_int sk_specific1 :7; /* Sense Key Specific */
170 u_int sksv :1; /* Sense Key Specific info valid */
171 u_char sk_specific2; /* Sense Key Specific */
172 u_char sk_specific3; /* Sense Key Specific */
173 u_char pad[2]; /* Padding */
177 struct atapi *ata; /* Controller structure */
178 int unit; /* IDE bus drive unit */
179 int lun; /* Logical device unit */
180 int flags; /* Device state flags */
181 int blksize; /* Block size (512 | 1024) */
182 struct buf_queue_head buf_queue; /* Queue of i/o requests */
183 struct atapi_params *param; /* Drive parameters table */
184 struct wst_header header; /* MODE SENSE param header */
185 struct wst_cappage cap; /* Capabilities page info */
188 static struct wst *wsttab[NUNIT]; /* Drive info by unit number */
189 static int wstnlun = 0; /* Number of config'd drives */
191 int wstattach(struct atapi *ata, int unit, struct atapi_params *ap, int debug);
192 static int wst_sense(struct wst *t);
193 static void wst_describe(struct wst *t);
194 static void wst_poll_dsc(struct wst *t);
195 static void wst_start(struct wst *t);
196 static void wst_done(struct wst *t, struct buf *bp, int resid, struct atapires result);
197 static int wst_error(struct wst *t, struct atapires result);
198 static void wst_drvinit(void *unused);
199 static int wst_space_cmd(struct wst *t, u_char function, u_int count);
200 static int wst_write_filemark(struct wst *t, u_char function);
201 static int wst_erase(struct wst *t);
202 static int wst_load_unload(struct wst *t, u_char finction);
203 static int wst_rewind(struct wst *t);
204 static void wst_reset(struct wst *t);
207 void wst_dump(int lun, char *label, void *data, int len);
210 wst_dump(int lun, char *label, void *data, int len)
214 printf("wst%d: %s %x", lun, label, *p++);
222 wstattach(struct atapi *ata, int unit, struct atapi_params *ap, int debug)
227 if (wstnlun >= NUNIT) {
228 printf("wst: too many units\n");
231 if (!atapi_request_immediate) {
232 printf("wst: configuration error, ATAPI core code not present!\n");
234 "wst: check `options ATAPI_STATIC' in your kernel config file!\n");
237 t = malloc(sizeof(struct wst), M_TEMP, M_NOWAIT);
239 printf("wst: out of memory\n");
243 bzero(t, sizeof(struct wst));
244 bufq_init(&t->buf_queue);
248 lun = t->lun = wstnlun;
250 t->flags = WST_MEDIA_CHANGED | WST_DEBUG;
258 make_dev(&wst_cdevsw, 0, UID_ROOT, GID_OPERATOR, 0640, "rwst%d", t->lun);
263 wst_sense(struct wst *t)
265 struct atapires result;
269 /* Get drive capabilities, some drives needs this repeated */
270 for (count = 0 ; count < 5 ; count++) {
271 result = atapi_request_immediate(t->ata, t->unit,
272 ATAPI_TAPE_MODE_SENSE,
273 8, /* DBD = 1 no block descr */
275 sizeof(buffer)>>8, sizeof(buffer),
277 0, 0, 0, 0, buffer, sizeof(buffer));
278 if (result.code == 0 || result.code == RES_UNDERRUN)
282 /* Some drives have shorter capabilities page. */
283 if (result.code == RES_UNDERRUN)
286 if (result.code == 0) {
287 bcopy(buffer, &t->header, sizeof(struct wst_header));
288 bcopy(buffer+sizeof(struct wst_header),
289 &t->cap, sizeof(struct wst_cappage));
290 if (t->cap.page_code != ATAPI_TAPE_CAP_PAGE)
292 t->cap.max_speed = ntohs(t->cap.max_speed);
293 t->cap.max_defects = ntohs(t->cap.max_defects);
294 t->cap.ctl = ntohs(t->cap.ctl);
295 t->cap.speed = ntohs(t->cap.speed);
296 t->cap.buffer_size = ntohs(t->cap.buffer_size);
297 t->blksize = (t->cap.blk512 ? 512 : (t->cap.blk1024 ? 1024 : 0));
304 wst_describe(struct wst *t)
306 printf("wst%d: ", t->lun);
307 switch (t->header.medium_type) {
308 case 0x00: printf("Drive empty"); break;
309 case 0x17: printf("Travan 1 (400 Mbyte) media"); break;
310 case 0xb6: printf("Travan 4 (4 Gbyte) media"); break;
311 default: printf("Unknown media (0x%x)", t->header.medium_type);
313 if (t->cap.readonly) printf(", readonly");
314 if (t->cap.reverse) printf(", reverse");
315 if (t->cap.eformat) printf(", eformat");
316 if (t->cap.qfa) printf(", qfa");
317 if (t->cap.lock) printf(", lock");
318 if (t->cap.locked) printf(", locked");
319 if (t->cap.prevent) printf(", prevent");
320 if (t->cap.eject) printf(", eject");
321 if (t->cap.disconnect) printf(", disconnect");
322 if (t->cap.ecc) printf(", ecc");
323 if (t->cap.compress) printf(", compress");
324 if (t->cap.blk512) printf(", 512b");
325 if (t->cap.blk1024) printf(", 1024b");
326 if (t->cap.slowb) printf(", slowb");
327 printf("\nwst%d: ", t->lun);
328 printf("Max speed=%dKb/s, ", t->cap.max_speed);
329 printf("Transfer limit=%d blocks, ", t->cap.ctl);
330 printf("Buffer size=%d blocks", t->cap.buffer_size);
335 wstopen(dev_t dev, int flags, int fmt, struct proc *p)
340 /* Check that the device number and that the ATAPI driver is loaded. */
341 if (lun >= wstnlun || !atapi_request_immediate) {
342 printf("ENXIO lun=%d, wstnlun=%d, im=%p\n",
343 lun, wstnlun, (void *)atapi_request_immediate);
347 if (t->flags == WST_OPEN)
350 printf("wst%d: Sense media type failed\n", t->lun);
351 t->flags &= ~WST_MEDIA_CHANGED;
352 t->flags &= ~(WST_DATA_WRITTEN | WST_FM_WRITTEN);
353 t->flags |= WST_OPEN;
358 wstclose(dev_t dev, int flags, int fmt, struct proc *p)
361 struct wst *t = wsttab[lun];
363 /* Flush buffers, some drives fail here, but they should report ctl = 0 */
364 if (t->cap.ctl && (t->flags & WST_DATA_WRITTEN))
365 wst_write_filemark(t, 0);
367 /* Write filemark if data written to tape */
368 if ((t->flags & (WST_DATA_WRITTEN | WST_FM_WRITTEN)) == WST_DATA_WRITTEN)
369 wst_write_filemark(t, WEOF_WRITE_MASK);
371 /* If minor is even rewind on close */
372 if (!(minor(dev) & 0x01))
375 t->flags &= ~WST_OPEN;
376 if (t->flags & WST_DEBUG)
377 printf("wst%d: %ud total bytes transferred\n", t->lun, wst_total);
378 t->flags &= ~WST_CTL_WARN;
383 wststrategy(struct buf *bp)
385 int lun = UNIT(bp->b_dev);
386 struct wst *t = wsttab[lun];
389 /* If it's a null transfer, return immediatly. */
390 if (bp->b_bcount == 0) {
396 /* Check for != blocksize requests */
397 if (bp->b_bcount % t->blksize) {
398 printf("wst%d: bad request, must be multiple of %d\n", lun, t->blksize);
400 bp->b_flags |= B_ERROR;
405 if (bp->b_bcount > t->blksize*t->cap.ctl) {
406 if ((t->flags & WST_CTL_WARN) == 0) {
407 printf("wst%d: WARNING: CTL exceeded %ld>%d\n",
408 lun, bp->b_bcount, t->blksize*t->cap.ctl);
409 t->flags |= WST_CTL_WARN;
414 wst_total += bp->b_bcount;
415 bufq_insert_tail(&t->buf_queue, bp);
421 wst_poll_dsc(struct wst *t)
423 /* We should use a final timeout here SOS XXX */
424 if (!(inb(t->ata->port + AR_STATUS) & ARS_DSC)) {
425 timeout((timeout_t*)wst_poll_dsc, t, DSC_POLL_INTERVAL);
428 t->ata->wait_for_dsc = 0;
433 wst_start(struct wst *t)
435 struct buf *bp = bufq_first(&t->buf_queue);
443 if (t->ata->wait_for_dsc)
444 printf("wst%d: ERROR! allready waiting for DSC\n", t->lun);
446 /* Sleep waiting for a ready drive (DSC) */
447 if (t->ata->use_dsc && !(inb(t->ata->port + AR_STATUS) & ARS_DSC)) {
448 t->ata->wait_for_dsc = 1;
449 timeout((timeout_t*)wst_poll_dsc, t, DSC_POLL_INTERVAL);
450 tsleep((caddr_t) t, 0, "wstdsc", 0);
453 bufq_remove(&t->buf_queue, bp);
454 blk_count = bp->b_bcount / t->blksize;
456 if (bp->b_flags & B_READ) {
457 op_code = ATAPI_TAPE_READ_CMD;
458 byte_count = bp->b_bcount;
460 op_code = ATAPI_TAPE_WRITE_CMD;
461 t->flags |= WST_DATA_WRITTEN;
462 byte_count = -bp->b_bcount;
465 atapi_request_callback(t->ata, t->unit, op_code, 1,
466 blk_count>>16, blk_count>>8, blk_count,
467 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
468 (u_char*) bp->b_data, byte_count,
469 (void*)wst_done, t, bp);
473 wst_done(struct wst *t, struct buf *bp, int resid,
474 struct atapires result)
477 printf("wst_done: ");
478 wst_error(t, result);
480 bp->b_flags |= B_ERROR;
490 wst_error(struct wst *t, struct atapires result)
492 struct wst_reqsense sense;
494 if (result.code != RES_ERR) {
495 printf("wst%d: ERROR code=%d, status=%b, error=%b\n", t->lun,
496 result.code, result.status, ARS_BITS, result.error, AER_BITS);
500 if ((result.error & AER_SKEY) && (result.status & ARS_CHECK)) {
501 atapi_request_immediate(t->ata, t->unit,
502 ATAPI_TAPE_REQUEST_SENSE,
503 0, 0, 0, sizeof(sense),
505 0, 0, 0, 0, (char*) &sense, sizeof(struct wst_reqsense));
506 /*wst_dump(t->lun, "req_sense", &sense, sizeof(struct wst_reqsense));*/
508 switch (result.error & AER_SKEY) {
509 case AER_SK_NOT_READY:
510 if (result.error & ~AER_SKEY) {
511 if (t->flags & WST_DEBUG)
512 printf("wst%d: not ready\n", t->lun);
515 if (!(t->flags & WST_MEDIA_CHANGED))
516 if (t->flags & WST_DEBUG)
517 printf("wst%d: no media\n", t->lun);
518 t->flags |= WST_MEDIA_CHANGED;
521 case AER_SK_BLANK_CHECK:
522 if (t->flags & WST_DEBUG)
523 printf("wst%d: EOD encountered\n", t->lun);
526 case AER_SK_MEDIUM_ERROR:
527 if (t->flags & WST_DEBUG)
528 printf("wst%d: nonrecovered data error\n", t->lun);
531 case AER_SK_HARDWARE_ERROR:
532 if (t->flags & WST_DEBUG)
533 printf("wst%d: nonrecovered hardware error\n", t->lun);
536 case AER_SK_ILLEGAL_REQUEST:
537 if (t->flags & WST_DEBUG)
538 printf("wst%d: invalid command\n", t->lun);
541 case AER_SK_UNIT_ATTENTION:
542 if (!(t->flags & WST_MEDIA_CHANGED))
543 printf("wst%d: media changed\n", t->lun);
544 t->flags |= WST_MEDIA_CHANGED;
547 case AER_SK_DATA_PROTECT:
548 if (t->flags & WST_DEBUG)
549 printf("wst%d: reading read protected data\n", t->lun);
552 case AER_SK_ABORTED_COMMAND:
553 if (t->flags & WST_DEBUG)
554 printf("wst%d: command aborted\n", t->lun);
557 case AER_SK_MISCOMPARE:
558 if (t->flags & WST_DEBUG)
559 printf("wst%d: data don't match medium\n", t->lun);
563 printf("wst%d: i/o error, status=%b, error=%b\n", t->lun,
564 result.status, ARS_BITS, result.error, AER_BITS);
566 printf("total=%u ERR=%x len=%ld ASC=%x ASCQ=%x\n",
567 wst_total, sense.error_code, (long)ntohl(sense.info),
568 sense.asc, sense.ascq);
573 wstioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
577 struct wst *t = wsttab[lun];
582 struct mtget *g = (struct mtget *) addr;
584 bzero(g, sizeof(struct mtget));
587 g->mt_blksiz = t->blksize;
588 g->mt_comp = t->cap.compress;
589 g->mt_density0 = 0; g->mt_density1 = 0;
590 g->mt_density2 = 0; g->mt_density3 = 0;
591 g->mt_blksiz0 = 0; g->mt_blksiz1 = 0;
592 g->mt_blksiz2 = 0; g->mt_blksiz3 = 0;
593 g->mt_comp0 = 0; g->mt_comp1 = 0;
594 g->mt_comp2 = 0; g->mt_comp3 = 0;
600 struct mtop *mt = (struct mtop *)addr;
602 switch ((short) (mt->mt_op)) {
604 for (i=0; i < mt->mt_count && !error; i++)
605 error = wst_write_filemark(t, WEOF_WRITE_MASK);
609 error = wst_space_cmd(t, SP_FM, mt->mt_count);
613 error = wst_space_cmd(t, SP_FM, -(mt->mt_count));
616 error = EINVAL; break;
618 error = EINVAL; break;
620 error = wst_rewind(t);
623 #if 1 /* Misuse as a reset func for now */
628 if (error = wst_rewind(t))
630 error = wst_load_unload(t, !LU_LOAD_MASK);
634 error = wst_write_filemark(t, 0);
637 error = EINVAL; break;
639 error = EINVAL; break;
641 error = EINVAL; break;
643 error = EINVAL; break;
645 error = wst_erase(t);
648 error = wst_space_cmd(t, SP_EOD, 0);
651 error = EINVAL; break;
653 error = wst_load_unload(t, LU_RETENSION_MASK|LU_LOAD_MASK);
667 wst_space_cmd(struct wst *t, u_char function, u_int count)
669 struct atapires result;
671 result = atapi_request_wait(t->ata, t->unit,
672 ATAPI_TAPE_SPACE_CMD, function,
673 count>>16, count>>8, count,
674 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0);
676 printf("wst_space_cmd: ");
677 wst_error(t, result);
684 wst_write_filemark(struct wst *t, u_char function)
686 struct atapires result;
689 if (t->flags & WST_FM_WRITTEN)
690 t->flags &= ~WST_DATA_WRITTEN;
692 t->flags |= WST_FM_WRITTEN;
694 result = atapi_request_wait(t->ata, t->unit,
695 ATAPI_TAPE_WEOF, 0, 0, 0, function,
696 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0);
698 printf("wst_write_filemark: ");
699 wst_error(t, result);
706 wst_load_unload(struct wst *t, u_char function)
708 struct atapires result;
710 result = atapi_request_wait(t->ata, t->unit,
711 ATAPI_TAPE_LOAD_UNLOAD, 0, 0, 0, function,
712 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0);
714 printf("wst_load_unload: ");
715 wst_error(t, result);
722 wst_erase(struct wst *t)
725 struct atapires result;
727 error = wst_rewind(t);
730 result = atapi_request_wait(t->ata, t->unit,
731 ATAPI_TAPE_ERASE, 3, 0, 0, 0,
732 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
735 printf("wst_erase: ");
736 wst_error(t, result);
743 wst_rewind(struct wst *t)
745 struct atapires result;
747 result = atapi_request_wait(t->ata, t->unit,
748 ATAPI_TAPE_REWIND, 0, 0, 0, 0,
749 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
752 printf("wst_rewind: ");
753 wst_error(t, result);
760 wst_reset(struct wst *t)
762 outb(t->ata->port + AR_DRIVE, ARD_DRIVE1);
764 outb(t->ata->port + AR_COMMAND, 0x08);
769 wst_drvinit(void *unused)
771 cdevsw_add(&wst_cdevsw);
774 SYSINIT(wstdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,wst_drvinit,NULL)