]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ata/atapi-tape.c
This commit was generated by cvs2svn to compensate for changes in r163820,
[FreeBSD/FreeBSD.git] / sys / dev / ata / atapi-tape.c
1 /*-
2  * Copyright (c) 1998 - 2006 Søren Schmidt <sos@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "opt_ata.h"
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/ata.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/malloc.h>
37 #include <sys/conf.h>
38 #include <sys/bio.h>
39 #include <sys/bus.h>
40 #include <sys/mtio.h>
41 #include <sys/devicestat.h>
42 #include <sys/sema.h>
43 #include <sys/taskqueue.h>
44 #include <vm/uma.h>
45 #include <machine/bus.h>
46 #include <dev/ata/ata-all.h>
47 #include <dev/ata/atapi-tape.h>
48 #include <ata_if.h>
49
50 /* device structure */
51 static  d_open_t        ast_open;
52 static  d_close_t       ast_close;
53 static  d_ioctl_t       ast_ioctl;
54 static  d_strategy_t    ast_strategy;
55 static struct cdevsw ast_cdevsw = {
56         .d_version =    D_VERSION,
57         .d_open =       ast_open,
58         .d_close =      ast_close,
59         .d_read =       physread,
60         .d_write =      physwrite,
61         .d_ioctl =      ast_ioctl,
62         .d_strategy =   ast_strategy,
63         .d_name =       "ast",
64         .d_flags =      D_TAPE | D_TRACKCLOSE,
65 };
66
67 /* prototypes */
68 static int ast_sense(device_t);
69 static void ast_describe(device_t);
70 static void ast_done(struct ata_request *);
71 static int ast_mode_sense(device_t, int, void *, int); 
72 static int ast_mode_select(device_t, void *, int);
73 static int ast_write_filemark(device_t, u_int8_t);
74 static int ast_read_position(device_t, int, struct ast_readposition *);
75 static int ast_space(device_t, u_int8_t, int32_t);
76 static int ast_locate(device_t, int, u_int32_t);
77 static int ast_prevent_allow(device_t, int);
78 static int ast_load_unload(device_t, u_int8_t);
79 static int ast_rewind(device_t);
80 static int ast_erase(device_t);
81 static int ast_test_ready(device_t);
82 static int ast_wait_dsc(device_t, int);
83
84 /* internal vars */
85 static u_int64_t ast_total = 0;
86 static MALLOC_DEFINE(M_AST, "ast_driver", "ATAPI tape driver buffers");
87
88 static int
89 ast_probe(device_t dev)
90 {
91     struct ata_device *atadev = device_get_softc(dev);
92
93     if ((atadev->param.config & ATA_PROTO_ATAPI) &&
94         (atadev->param.config & ATA_ATAPI_TYPE_MASK) == ATA_ATAPI_TYPE_TAPE)
95         return 0;
96     else
97         return ENXIO;
98 }
99
100 static int
101 ast_attach(device_t dev)
102 {
103     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
104     struct ata_device *atadev = device_get_softc(dev);
105     struct ast_softc *stp;
106     struct ast_readposition position;
107     struct cdev *device;
108
109     if (!(stp = malloc(sizeof(struct ast_softc), M_AST, M_NOWAIT | M_ZERO))) {
110         device_printf(dev, "out of memory\n");
111         return ENOMEM;
112     }
113     device_set_ivars(dev, stp);
114     ATA_SETMODE(device_get_parent(dev), dev);
115
116     if (ast_sense(dev)) {
117         device_set_ivars(dev, NULL);
118         free(stp, M_AST);
119         return ENXIO;
120     }
121     if (!strcmp(atadev->param.model, "OnStream DI-30")) {
122         struct ast_transferpage transfer;
123         struct ast_identifypage identify;
124
125         stp->flags |= F_ONSTREAM;
126         bzero(&transfer, sizeof(struct ast_transferpage));
127         ast_mode_sense(dev, ATAPI_TAPE_TRANSFER_PAGE,
128                        &transfer, sizeof(transfer));
129         bzero(&identify, sizeof(struct ast_identifypage));
130         ast_mode_sense(dev, ATAPI_TAPE_IDENTIFY_PAGE,
131                        &identify, sizeof(identify));
132         strncpy(identify.ident, "FBSD", 4);
133         ast_mode_select(dev, &identify, sizeof(identify));
134         ast_read_position(dev, 0, &position);
135     }
136
137     stp->stats = devstat_new_entry("ast", device_get_unit(dev), DEV_BSIZE,
138                       DEVSTAT_NO_ORDERED_TAGS,
139                       DEVSTAT_TYPE_SEQUENTIAL | DEVSTAT_TYPE_IF_IDE,
140                       DEVSTAT_PRIORITY_TAPE);
141     device = make_dev(&ast_cdevsw, 2 * device_get_unit(dev),
142                       UID_ROOT, GID_OPERATOR, 0640, "ast%d",
143                       device_get_unit(dev));
144     device->si_drv1 = dev;
145     if (ch->dma)
146         device->si_iosize_max = ch->dma->max_iosize;
147     else
148         device->si_iosize_max = DFLTPHYS;
149     stp->dev1 = device;
150     device = make_dev(&ast_cdevsw, 2 * device_get_unit(dev) + 1,
151                       UID_ROOT, GID_OPERATOR, 0640, "nast%d",
152                       device_get_unit(dev));
153     device->si_drv1 = dev;
154     if (ch->dma)
155         device->si_iosize_max = ch->dma->max_iosize;
156     else
157         device->si_iosize_max = DFLTPHYS;
158     stp->dev2 = device;
159
160     /* announce we are here and ready */
161     ast_describe(dev);
162     return 0;
163 }
164
165 static int      
166 ast_detach(device_t dev)
167 {   
168     struct ast_softc *stp = device_get_ivars(dev);
169     
170     /* detroy devices from the system so we dont get any further requests */
171     destroy_dev(stp->dev1);
172     destroy_dev(stp->dev2);
173
174     /* fail requests on the queue and any thats "in flight" for this device */
175     ata_fail_requests(dev);
176
177     /* dont leave anything behind */
178     devstat_remove_entry(stp->stats);
179     device_set_ivars(dev, NULL);
180     free(stp, M_AST);
181     return 0;
182 }
183
184 static void
185 ast_shutdown(device_t dev)
186 {
187     struct ata_device *atadev = device_get_softc(dev);
188
189     if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
190         ata_controlcmd(dev, ATA_FLUSHCACHE, 0, 0, 0);
191 }
192
193 static int
194 ast_reinit(device_t dev)
195 {
196     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
197     struct ata_device *atadev = device_get_softc(dev);
198     struct ast_softc *stp = device_get_ivars(dev);
199
200     if (((atadev->unit == ATA_MASTER) && !(ch->devices & ATA_ATAPI_MASTER)) ||
201         ((atadev->unit == ATA_SLAVE) && !(ch->devices & ATA_ATAPI_SLAVE))) {
202         device_set_ivars(dev, NULL);
203         free(stp, M_AST);
204         return 1;
205     }
206     ATA_SETMODE(device_get_parent(dev), dev);
207     return 0;
208 }
209
210 static int
211 ast_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
212 {
213     device_t dev = cdev->si_drv1;
214     struct ata_device *atadev = device_get_softc(dev);
215     struct ast_softc *stp = device_get_ivars(dev);
216
217     if (!stp)
218         return ENXIO;
219     if (!device_is_attached(dev))
220         return EBUSY;
221
222     ast_test_ready(dev);
223     if (stp->cap.lock)
224         ast_prevent_allow(dev, 1);
225     if (ast_sense(dev))
226         device_printf(dev, "sense media type failed\n");
227
228     atadev->flags &= ~ATA_D_MEDIA_CHANGED;
229     stp->flags &= ~(F_DATA_WRITTEN | F_FM_WRITTEN);
230     ast_total = 0;
231     return 0;
232 }
233
234 static int 
235 ast_close(struct cdev *cdev, int flags, int fmt, struct thread *td)
236 {
237     device_t dev = cdev->si_drv1;
238     struct ast_softc *stp = device_get_ivars(dev);
239
240     /* flush buffers, some drives fail here, they should report ctl = 0 */
241     if (stp->cap.ctl && (stp->flags & F_DATA_WRITTEN))
242         ast_write_filemark(dev, 0);
243
244     /* write filemark if data written to tape */
245     if (!(stp->flags & F_ONSTREAM) &&
246         (stp->flags & (F_DATA_WRITTEN | F_FM_WRITTEN)) == F_DATA_WRITTEN)
247         ast_write_filemark(dev, ATAPI_WF_WRITE);
248
249     /* if minor is even rewind on close */
250     if (!(minor(cdev) & 0x01))
251         ast_rewind(dev);
252
253     if (stp->cap.lock && count_dev(cdev) == 1)
254         ast_prevent_allow(dev, 0);
255
256     stp->flags &= ~F_CTL_WARN;
257 #ifdef AST_DEBUG
258     device_printf(dev, "%ju total bytes transferred\n", (uintmax_t)ast_total);
259 #endif
260     return 0;
261 }
262
263 static int 
264 ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int flag, struct thread *td)
265 {
266     device_t dev = cdev->si_drv1;
267     struct ast_softc *stp = device_get_ivars(dev);
268     int error = 0;
269
270     switch (cmd) {
271     case MTIOCGET:
272         {
273             struct mtget *g = (struct mtget *) data;
274
275             bzero(g, sizeof(struct mtget));
276             g->mt_type = 7;
277             g->mt_density = 1;
278             g->mt_blksiz = stp->blksize;
279             g->mt_comp = stp->cap.compress;
280             g->mt_density0 = 0; g->mt_density1 = 0;
281             g->mt_density2 = 0; g->mt_density3 = 0;
282             g->mt_blksiz0 = 0; g->mt_blksiz1 = 0;
283             g->mt_blksiz2 = 0; g->mt_blksiz3 = 0;
284             g->mt_comp0 = 0; g->mt_comp1 = 0;
285             g->mt_comp2 = 0; g->mt_comp3 = 0;
286         }
287         break;   
288
289     case MTIOCTOP:
290         {       
291             int i;
292             struct mtop *mt = (struct mtop *)data;
293
294             switch ((int16_t) (mt->mt_op)) {
295
296             case MTWEOF:
297                 for (i=0; i < mt->mt_count && !error; i++)
298                     error = ast_write_filemark(dev, ATAPI_WF_WRITE);
299                 break;
300
301             case MTFSF:
302                 if (mt->mt_count)
303                     error = ast_space(dev, ATAPI_SP_FM, mt->mt_count);
304                 break;
305
306             case MTBSF:
307                 if (mt->mt_count)
308                     error = ast_space(dev, ATAPI_SP_FM, -(mt->mt_count));
309                 break;
310
311             case MTREW:
312                 error = ast_rewind(dev);
313                 break;
314
315             case MTOFFL:
316                 error = ast_load_unload(dev, ATAPI_SS_EJECT);
317                 break;
318
319             case MTNOP:
320                 error = ast_write_filemark(dev, 0);
321                 break;
322
323             case MTERASE:
324                 error = ast_erase(dev);
325                 break;
326
327             case MTEOD:
328                 error = ast_space(dev, ATAPI_SP_EOD, 0);
329                 break;
330
331             case MTRETENS:
332                 error = ast_load_unload(dev, ATAPI_SS_RETENSION|ATAPI_SS_LOAD);
333                 break;
334
335             case MTFSR:         
336             case MTBSR:
337             case MTCACHE:
338             case MTNOCACHE:
339             case MTSETBSIZ:
340             case MTSETDNSTY:
341             case MTCOMP:
342             default:
343                 error = EINVAL;
344             }
345         }
346         break;
347
348     case MTIOCRDSPOS:
349         {
350             struct ast_readposition position;
351
352             if ((error = ast_read_position(dev, 0, &position)))
353                 break;
354             *(u_int32_t *)data = position.tape;
355         }
356         break;
357
358     case MTIOCRDHPOS:
359         {
360             struct ast_readposition position;
361
362             if ((error = ast_read_position(dev, 1, &position)))
363                 break;
364             *(u_int32_t *)data = position.tape;
365         }
366         break;
367
368     case MTIOCSLOCATE:
369         error = ast_locate(dev, 0, *(u_int32_t *)data);
370         break;
371
372     case MTIOCHLOCATE:
373         error = ast_locate(dev, 1, *(u_int32_t *)data);
374         break;
375
376     default:
377         error = ata_device_ioctl(dev, cmd, data);
378     }
379     return error;
380 }
381
382 static void 
383 ast_strategy(struct bio *bp)
384 {
385     device_t dev = bp->bio_dev->si_drv1;
386     struct ata_device *atadev = device_get_softc(dev);
387     struct ast_softc *stp = device_get_ivars(dev);
388     struct ata_request *request;
389     u_int32_t blkcount;
390     int8_t ccb[16];
391
392     /* if it's a null transfer, return immediatly. */
393     if (bp->bio_bcount == 0) {
394         bp->bio_resid = 0;
395         biodone(bp);
396         return;
397     }
398     if (!(bp->bio_cmd == BIO_READ) && stp->flags & F_WRITEPROTECT) {
399         biofinish(bp, NULL, EPERM);
400         return;
401     }
402         
403     /* check for != blocksize requests */
404     if (bp->bio_bcount % stp->blksize) {
405         device_printf(dev, "transfers must be multiple of %d\n", stp->blksize);
406         biofinish(bp, NULL, EIO);
407         return;
408     }
409
410     /* warn about transfers bigger than the device suggests */
411     if (bp->bio_bcount > stp->blksize * stp->cap.ctl) {  
412         if ((stp->flags & F_CTL_WARN) == 0) {
413             device_printf(dev, "WARNING: CTL exceeded %ld>%d\n",
414                           bp->bio_bcount, stp->blksize * stp->cap.ctl);
415             stp->flags |= F_CTL_WARN;
416         }
417     }
418
419     bzero(ccb, sizeof(ccb));
420
421     if (bp->bio_cmd == BIO_READ)
422         ccb[0] = ATAPI_READ;
423     else
424         ccb[0] = ATAPI_WRITE;
425     
426     blkcount = bp->bio_bcount / stp->blksize;
427
428     ccb[1] = 1;
429     ccb[2] = blkcount >> 16;
430     ccb[3] = blkcount >> 8;
431     ccb[4] = blkcount;
432
433     if (!(request = ata_alloc_request())) {
434         biofinish(bp, NULL, ENOMEM);
435         return;
436     }
437     request->dev = dev;
438     request->driver = bp;
439     bcopy(ccb, request->u.atapi.ccb,
440           (atadev->param.config & ATA_PROTO_MASK) == 
441           ATA_PROTO_ATAPI_12 ? 16 : 12);
442     request->data = bp->bio_data;
443     request->bytecount = blkcount * stp->blksize;
444     request->transfersize = min(request->bytecount, 65534);
445     request->timeout = (ccb[0] == ATAPI_WRITE_BIG) ? 180 : 120;
446     request->retries = 2;
447     request->callback = ast_done;
448     switch (bp->bio_cmd) {
449     case BIO_READ:
450         request->flags |= (ATA_R_ATAPI | ATA_R_READ);
451         break;
452     case BIO_WRITE:
453         request->flags |= (ATA_R_ATAPI | ATA_R_WRITE);
454         break;
455     default:
456         device_printf(dev, "unknown BIO operation\n");
457         ata_free_request(request);
458         biofinish(bp, NULL, EIO);
459         return;
460     }
461     devstat_start_transaction_bio(stp->stats, bp);
462     ata_queue_request(request);
463 }
464
465 static void 
466 ast_done(struct ata_request *request)
467 {
468     struct ast_softc *stp = device_get_ivars(request->dev);
469     struct bio *bp = request->driver;
470
471     /* finish up transfer */
472     if ((bp->bio_error = request->result))
473         bp->bio_flags |= BIO_ERROR;
474     if (bp->bio_cmd == BIO_WRITE)
475         stp->flags |= F_DATA_WRITTEN;
476     bp->bio_resid = bp->bio_bcount - request->donecount;
477     ast_total += (bp->bio_bcount - bp->bio_resid);
478     biofinish(bp, stp->stats, 0);
479     ata_free_request(request);
480 }
481
482 static int
483 ast_sense(device_t dev)
484 {
485     struct ast_softc *stp = device_get_ivars(dev);
486     int count;
487
488     /* get drive capabilities, some bugridden drives needs this repeated */
489     for (count = 0 ; count < 5 ; count++) {
490         if (!ast_mode_sense(dev, ATAPI_TAPE_CAP_PAGE,
491                             &stp->cap, sizeof(stp->cap)) &&
492             stp->cap.page_code == ATAPI_TAPE_CAP_PAGE) {
493             if (stp->cap.blk32k)
494                 stp->blksize = 32768;
495             if (stp->cap.blk1024)
496                 stp->blksize = 1024;
497             if (stp->cap.blk512)
498                 stp->blksize = 512;
499             if (!stp->blksize)
500                 continue;
501             stp->cap.max_speed = ntohs(stp->cap.max_speed);
502             stp->cap.max_defects = ntohs(stp->cap.max_defects);
503             stp->cap.ctl = ntohs(stp->cap.ctl);
504             stp->cap.speed = ntohs(stp->cap.speed);
505             stp->cap.buffer_size = ntohs(stp->cap.buffer_size);
506             return 0;
507         }
508     }
509     return 1;
510 }
511
512 static int
513 ast_mode_sense(device_t dev, int page, void *pagebuf, int pagesize)
514 {
515     int8_t ccb[16] = { ATAPI_MODE_SENSE, 0x08, page, pagesize>>8, pagesize,
516                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
517     int error;
518  
519     error = ata_atapicmd(dev, ccb, pagebuf, pagesize, ATA_R_READ, 10);
520     return error;
521 }
522
523 static int       
524 ast_mode_select(device_t dev, void *pagebuf, int pagesize)
525 {
526     int8_t ccb[16] = { ATAPI_MODE_SELECT, 0x10, 0, pagesize>>8, pagesize,
527                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
528      
529     return ata_atapicmd(dev, ccb, pagebuf, pagesize, 0, 10);
530 }
531
532 static int
533 ast_write_filemark(device_t dev, u_int8_t function)
534 {
535     struct ast_softc *stp = device_get_ivars(dev);
536     int8_t ccb[16] = { ATAPI_WEOF, 0x01, 0, 0, function, 0, 0, 0,
537                        0, 0, 0, 0, 0, 0, 0, 0 };
538     int error;
539
540     if (stp->flags & F_ONSTREAM)
541         ccb[4] = 0x00;          /* only flush buffers supported */
542     else {
543         if (function) {
544             if (stp->flags & F_FM_WRITTEN)
545                 stp->flags &= ~F_DATA_WRITTEN;
546             else
547                 stp->flags |= F_FM_WRITTEN;
548         }
549     }
550     error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
551     if (error)
552         return error;
553     return ast_wait_dsc(dev, 10*60);
554 }
555
556 static int
557 ast_read_position(device_t dev, int hard, struct ast_readposition *position)
558 {
559     int8_t ccb[16] = { ATAPI_READ_POSITION, (hard ? 0x01 : 0), 0, 0, 0, 0, 0, 0,
560                        0, 0, 0, 0, 0, 0, 0, 0 };
561     int error;
562
563     error = ata_atapicmd(dev, ccb, (caddr_t)position, 
564                          sizeof(struct ast_readposition), ATA_R_READ, 10);
565     position->tape = ntohl(position->tape);
566     position->host = ntohl(position->host);
567     return error;
568 }
569
570 static int
571 ast_space(device_t dev, u_int8_t function, int32_t count)
572 {
573     int8_t ccb[16] = { ATAPI_SPACE, function, count>>16, count>>8, count,
574                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
575
576     return ata_atapicmd(dev, ccb, NULL, 0, 0, 60*60);
577 }
578
579 static int
580 ast_locate(device_t dev, int hard, u_int32_t pos)
581 {
582     int8_t ccb[16] = { ATAPI_LOCATE, 0x01 | (hard ? 0x4 : 0), 0,
583                        pos>>24, pos>>16, pos>>8, pos,
584                        0, 0, 0, 0, 0, 0, 0, 0, 0 };
585     int error;
586
587     error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
588     if (error)
589         return error;
590     return ast_wait_dsc(dev, 60*60);
591 }
592
593 static int
594 ast_prevent_allow(device_t dev, int lock)
595 {
596     int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
597                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
598
599     return ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
600 }
601
602 static int
603 ast_load_unload(device_t dev, u_int8_t function)
604 {
605     struct ast_softc *stp = device_get_ivars(dev);
606     int8_t ccb[16] = { ATAPI_START_STOP, 0x01, 0, 0, function, 0, 0, 0,
607                        0, 0, 0, 0, 0, 0, 0, 0 };
608     int error;
609
610     if ((function & ATAPI_SS_EJECT) && !stp->cap.eject)
611         return 0;
612     error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
613     if (error)
614         return error;
615     tsleep((caddr_t)&error, PRIBIO, "astlu", 1 * hz);
616     if (function == ATAPI_SS_EJECT)
617         return 0;
618     return ast_wait_dsc(dev, 60*60);
619 }
620
621 static int
622 ast_rewind(device_t dev)
623 {
624     int8_t ccb[16] = { ATAPI_REZERO, 0x01, 0, 0, 0, 0, 0, 0,
625                        0, 0, 0, 0, 0, 0, 0, 0 };
626     int error;
627
628     error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
629     if (error)
630         return error;
631     return ast_wait_dsc(dev, 60*60);
632 }
633
634 static int
635 ast_erase(device_t dev)
636 {
637     int8_t ccb[16] = { ATAPI_ERASE, 3, 0, 0, 0, 0, 0, 0,
638                        0, 0, 0, 0, 0, 0, 0, 0 };
639     int error;
640
641     if ((error = ast_rewind(dev)))
642         return error;
643
644     return ata_atapicmd(dev, ccb, NULL, 0, 0, 60*60);
645 }
646
647 static int
648 ast_test_ready(device_t dev)
649 {
650     int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
651                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
652
653     return ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
654 }
655
656 static int
657 ast_wait_dsc(device_t dev, int timeout)
658 {
659     int error = 0;
660     int8_t ccb[16] = { ATAPI_POLL_DSC, 0, 0, 0, 0,
661                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
662
663     timeout *= hz;
664     while (timeout > 0) {
665         error = ata_atapicmd(dev, ccb, NULL, 0, 0, 0);
666         if (error != EBUSY)
667             break;
668         tsleep(&error, PRIBIO, "atpwt", hz / 2);
669         timeout -= (hz / 2);
670     }
671     return error;
672 }
673
674 static void 
675 ast_describe(device_t dev)
676 {
677     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
678     struct ata_device *atadev = device_get_softc(dev);
679     struct ast_softc *stp = device_get_ivars(dev);
680
681     if (bootverbose) {
682         device_printf(dev, "<%.40s/%.8s> tape drive at ata%d as %s\n",
683                       atadev->param.model, atadev->param.revision,
684                       device_get_unit(ch->dev),
685                       (atadev->unit == ATA_MASTER) ? "master" : "slave");
686         device_printf(dev, "%dKB/s, ", stp->cap.max_speed);
687         printf("transfer limit %d blk%s, ",
688                stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : "");
689         printf("%dKB buffer, ", (stp->cap.buffer_size * DEV_BSIZE) / 1024);
690         printf("%s\n", ata_mode2str(atadev->mode));
691         device_printf(dev, "Medium: ");
692         switch (stp->cap.medium_type) {
693             case 0x00:
694                 printf("none"); break;
695             case 0x17:
696                 printf("Travan 1 (400 Mbyte)"); break;
697             case 0xb6:
698                 printf("Travan 4 (4 Gbyte)"); break;
699             case 0xda:
700                 printf("OnStream ADR (15Gyte)"); break;
701             default:
702                 printf("unknown (0x%x)", stp->cap.medium_type);
703         }
704         if (stp->cap.readonly) printf(", readonly");
705         if (stp->cap.reverse) printf(", reverse");
706         if (stp->cap.eformat) printf(", eformat");
707         if (stp->cap.qfa) printf(", qfa");
708         if (stp->cap.lock) printf(", lock");
709         if (stp->cap.locked) printf(", locked");
710         if (stp->cap.prevent) printf(", prevent");
711         if (stp->cap.eject) printf(", eject");
712         if (stp->cap.disconnect) printf(", disconnect");
713         if (stp->cap.ecc) printf(", ecc");
714         if (stp->cap.compress) printf(", compress");
715         if (stp->cap.blk512) printf(", 512b");
716         if (stp->cap.blk1024) printf(", 1024b");
717         if (stp->cap.blk32k) printf(", 32kb");
718         printf("\n");
719     }
720     else {
721         device_printf(dev, "TAPE <%.40s/%.8s> at ata%d-%s %s\n",
722                       atadev->param.model, atadev->param.revision,
723                       device_get_unit(ch->dev),
724                       (atadev->unit == ATA_MASTER) ? "master" : "slave",
725                       ata_mode2str(atadev->mode));
726     }
727 }
728
729 static device_method_t ast_methods[] = {
730     /* device interface */
731     DEVMETHOD(device_probe,     ast_probe),
732     DEVMETHOD(device_attach,    ast_attach),
733     DEVMETHOD(device_detach,    ast_detach),
734     DEVMETHOD(device_shutdown,  ast_shutdown),
735                            
736     /* ATA methods */
737     DEVMETHOD(ata_reinit,       ast_reinit),
738
739     { 0, 0 }
740 };
741             
742 static driver_t ast_driver = {
743     "ast",
744     ast_methods,
745     0,
746 };
747
748 static devclass_t ast_devclass;
749
750 DRIVER_MODULE(ast, ata, ast_driver, ast_devclass, NULL, NULL);
751 MODULE_VERSION(ast, 1);
752 MODULE_DEPEND(ast, ata, 1, 1, 1);