]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/ata/atapi-tape.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / ata / atapi-tape.c
1 /*-
2  * Copyright (c) 1998 - 2007 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
199     if (((atadev->unit == ATA_MASTER) && !(ch->devices & ATA_ATAPI_MASTER)) ||
200         ((atadev->unit == ATA_SLAVE) && !(ch->devices & ATA_ATAPI_SLAVE))) {
201         return 1;
202     }
203     ATA_SETMODE(device_get_parent(dev), dev);
204     return 0;
205 }
206
207 static int
208 ast_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
209 {
210     device_t dev = cdev->si_drv1;
211     struct ata_device *atadev = device_get_softc(dev);
212     struct ast_softc *stp = device_get_ivars(dev);
213
214     if (!stp)
215         return ENXIO;
216     if (!device_is_attached(dev))
217         return EBUSY;
218
219     ast_test_ready(dev);
220     if (stp->cap.lock)
221         ast_prevent_allow(dev, 1);
222     if (ast_sense(dev))
223         device_printf(dev, "sense media type failed\n");
224
225     atadev->flags &= ~ATA_D_MEDIA_CHANGED;
226     stp->flags &= ~(F_DATA_WRITTEN | F_FM_WRITTEN);
227     ast_total = 0;
228     return 0;
229 }
230
231 static int 
232 ast_close(struct cdev *cdev, int flags, int fmt, struct thread *td)
233 {
234     device_t dev = cdev->si_drv1;
235     struct ast_softc *stp = device_get_ivars(dev);
236
237     /* flush buffers, some drives fail here, they should report ctl = 0 */
238     if (stp->cap.ctl && (stp->flags & F_DATA_WRITTEN))
239         ast_write_filemark(dev, 0);
240
241     /* write filemark if data written to tape */
242     if (!(stp->flags & F_ONSTREAM) &&
243         (stp->flags & (F_DATA_WRITTEN | F_FM_WRITTEN)) == F_DATA_WRITTEN)
244         ast_write_filemark(dev, ATAPI_WF_WRITE);
245
246     /* if minor is even rewind on close */
247     if (!(minor(cdev) & 0x01))
248         ast_rewind(dev);
249
250     if (stp->cap.lock && count_dev(cdev) == 1)
251         ast_prevent_allow(dev, 0);
252
253     stp->flags &= ~F_CTL_WARN;
254 #ifdef AST_DEBUG
255     device_printf(dev, "%ju total bytes transferred\n", (uintmax_t)ast_total);
256 #endif
257     return 0;
258 }
259
260 static int 
261 ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int flag, struct thread *td)
262 {
263     device_t dev = cdev->si_drv1;
264     struct ast_softc *stp = device_get_ivars(dev);
265     int error = 0;
266
267     switch (cmd) {
268     case MTIOCGET:
269         {
270             struct mtget *g = (struct mtget *) data;
271
272             bzero(g, sizeof(struct mtget));
273             g->mt_type = 7;
274             g->mt_density = 1;
275             g->mt_blksiz = stp->blksize;
276             g->mt_comp = stp->cap.compress;
277             g->mt_density0 = 0; g->mt_density1 = 0;
278             g->mt_density2 = 0; g->mt_density3 = 0;
279             g->mt_blksiz0 = 0; g->mt_blksiz1 = 0;
280             g->mt_blksiz2 = 0; g->mt_blksiz3 = 0;
281             g->mt_comp0 = 0; g->mt_comp1 = 0;
282             g->mt_comp2 = 0; g->mt_comp3 = 0;
283         }
284         break;   
285
286     case MTIOCTOP:
287         {       
288             int i;
289             struct mtop *mt = (struct mtop *)data;
290
291             switch ((int16_t) (mt->mt_op)) {
292
293             case MTWEOF:
294                 for (i=0; i < mt->mt_count && !error; i++)
295                     error = ast_write_filemark(dev, ATAPI_WF_WRITE);
296                 break;
297
298             case MTFSF:
299                 if (mt->mt_count)
300                     error = ast_space(dev, ATAPI_SP_FM, mt->mt_count);
301                 break;
302
303             case MTBSF:
304                 if (mt->mt_count)
305                     error = ast_space(dev, ATAPI_SP_FM, -(mt->mt_count));
306                 break;
307
308             case MTREW:
309                 error = ast_rewind(dev);
310                 break;
311
312             case MTOFFL:
313                 error = ast_load_unload(dev, ATAPI_SS_EJECT);
314                 break;
315
316             case MTNOP:
317                 error = ast_write_filemark(dev, 0);
318                 break;
319
320             case MTERASE:
321                 error = ast_erase(dev);
322                 break;
323
324             case MTEOD:
325                 error = ast_space(dev, ATAPI_SP_EOD, 0);
326                 break;
327
328             case MTRETENS:
329                 error = ast_load_unload(dev, ATAPI_SS_RETENSION|ATAPI_SS_LOAD);
330                 break;
331
332             case MTFSR:         
333             case MTBSR:
334             case MTCACHE:
335             case MTNOCACHE:
336             case MTSETBSIZ:
337             case MTSETDNSTY:
338             case MTCOMP:
339             default:
340                 error = EINVAL;
341             }
342         }
343         break;
344
345     case MTIOCRDSPOS:
346         {
347             struct ast_readposition position;
348
349             if ((error = ast_read_position(dev, 0, &position)))
350                 break;
351             *(u_int32_t *)data = position.tape;
352         }
353         break;
354
355     case MTIOCRDHPOS:
356         {
357             struct ast_readposition position;
358
359             if ((error = ast_read_position(dev, 1, &position)))
360                 break;
361             *(u_int32_t *)data = position.tape;
362         }
363         break;
364
365     case MTIOCSLOCATE:
366         error = ast_locate(dev, 0, *(u_int32_t *)data);
367         break;
368
369     case MTIOCHLOCATE:
370         error = ast_locate(dev, 1, *(u_int32_t *)data);
371         break;
372
373     default:
374         error = ata_device_ioctl(dev, cmd, data);
375     }
376     return error;
377 }
378
379 static void 
380 ast_strategy(struct bio *bp)
381 {
382     device_t dev = bp->bio_dev->si_drv1;
383     struct ata_device *atadev = device_get_softc(dev);
384     struct ast_softc *stp = device_get_ivars(dev);
385     struct ata_request *request;
386     u_int32_t blkcount;
387     int8_t ccb[16];
388
389     /* if it's a null transfer, return immediatly. */
390     if (bp->bio_bcount == 0) {
391         bp->bio_resid = 0;
392         biodone(bp);
393         return;
394     }
395     if (!(bp->bio_cmd == BIO_READ) && stp->flags & F_WRITEPROTECT) {
396         biofinish(bp, NULL, EPERM);
397         return;
398     }
399         
400     /* check for != blocksize requests */
401     if (bp->bio_bcount % stp->blksize) {
402         device_printf(dev, "transfers must be multiple of %d\n", stp->blksize);
403         biofinish(bp, NULL, EIO);
404         return;
405     }
406
407     /* warn about transfers bigger than the device suggests */
408     if (bp->bio_bcount > stp->blksize * stp->cap.ctl) {  
409         if ((stp->flags & F_CTL_WARN) == 0) {
410             device_printf(dev, "WARNING: CTL exceeded %ld>%d\n",
411                           bp->bio_bcount, stp->blksize * stp->cap.ctl);
412             stp->flags |= F_CTL_WARN;
413         }
414     }
415
416     bzero(ccb, sizeof(ccb));
417
418     if (bp->bio_cmd == BIO_READ)
419         ccb[0] = ATAPI_READ;
420     else
421         ccb[0] = ATAPI_WRITE;
422     
423     blkcount = bp->bio_bcount / stp->blksize;
424
425     ccb[1] = 1;
426     ccb[2] = blkcount >> 16;
427     ccb[3] = blkcount >> 8;
428     ccb[4] = blkcount;
429
430     if (!(request = ata_alloc_request())) {
431         biofinish(bp, NULL, ENOMEM);
432         return;
433     }
434     request->dev = dev;
435     request->driver = bp;
436     bcopy(ccb, request->u.atapi.ccb,
437           (atadev->param.config & ATA_PROTO_MASK) == 
438           ATA_PROTO_ATAPI_12 ? 16 : 12);
439     request->data = bp->bio_data;
440     request->bytecount = blkcount * stp->blksize;
441     request->transfersize = min(request->bytecount, 65534);
442     request->timeout = (ccb[0] == ATAPI_WRITE_BIG) ? 180 : 120;
443     request->retries = 2;
444     request->callback = ast_done;
445     switch (bp->bio_cmd) {
446     case BIO_READ:
447         request->flags |= (ATA_R_ATAPI | ATA_R_READ);
448         break;
449     case BIO_WRITE:
450         request->flags |= (ATA_R_ATAPI | ATA_R_WRITE);
451         break;
452     default:
453         device_printf(dev, "unknown BIO operation\n");
454         ata_free_request(request);
455         biofinish(bp, NULL, EIO);
456         return;
457     }
458     devstat_start_transaction_bio(stp->stats, bp);
459     ata_queue_request(request);
460 }
461
462 static void 
463 ast_done(struct ata_request *request)
464 {
465     struct ast_softc *stp = device_get_ivars(request->dev);
466     struct bio *bp = request->driver;
467
468     /* finish up transfer */
469     if ((bp->bio_error = request->result))
470         bp->bio_flags |= BIO_ERROR;
471     if (bp->bio_cmd == BIO_WRITE)
472         stp->flags |= F_DATA_WRITTEN;
473     bp->bio_resid = bp->bio_bcount - request->donecount;
474     ast_total += (bp->bio_bcount - bp->bio_resid);
475     biofinish(bp, stp->stats, 0);
476     ata_free_request(request);
477 }
478
479 static int
480 ast_sense(device_t dev)
481 {
482     struct ast_softc *stp = device_get_ivars(dev);
483     int count;
484
485     /* get drive capabilities, some bugridden drives needs this repeated */
486     for (count = 0 ; count < 5 ; count++) {
487         if (!ast_mode_sense(dev, ATAPI_TAPE_CAP_PAGE,
488                             &stp->cap, sizeof(stp->cap)) &&
489             stp->cap.page_code == ATAPI_TAPE_CAP_PAGE) {
490             if (stp->cap.blk32k)
491                 stp->blksize = 32768;
492             if (stp->cap.blk1024)
493                 stp->blksize = 1024;
494             if (stp->cap.blk512)
495                 stp->blksize = 512;
496             if (!stp->blksize)
497                 continue;
498             stp->cap.max_speed = ntohs(stp->cap.max_speed);
499             stp->cap.max_defects = ntohs(stp->cap.max_defects);
500             stp->cap.ctl = ntohs(stp->cap.ctl);
501             stp->cap.speed = ntohs(stp->cap.speed);
502             stp->cap.buffer_size = ntohs(stp->cap.buffer_size);
503             return 0;
504         }
505     }
506     return 1;
507 }
508
509 static int
510 ast_mode_sense(device_t dev, int page, void *pagebuf, int pagesize)
511 {
512     int8_t ccb[16] = { ATAPI_MODE_SENSE, 0x08, page, pagesize>>8, pagesize,
513                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
514     int error;
515  
516     error = ata_atapicmd(dev, ccb, pagebuf, pagesize, ATA_R_READ, 10);
517     return error;
518 }
519
520 static int       
521 ast_mode_select(device_t dev, void *pagebuf, int pagesize)
522 {
523     int8_t ccb[16] = { ATAPI_MODE_SELECT, 0x10, 0, pagesize>>8, pagesize,
524                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
525      
526     return ata_atapicmd(dev, ccb, pagebuf, pagesize, 0, 10);
527 }
528
529 static int
530 ast_write_filemark(device_t dev, u_int8_t function)
531 {
532     struct ast_softc *stp = device_get_ivars(dev);
533     int8_t ccb[16] = { ATAPI_WEOF, 0x01, 0, 0, function, 0, 0, 0,
534                        0, 0, 0, 0, 0, 0, 0, 0 };
535     int error;
536
537     if (stp->flags & F_ONSTREAM)
538         ccb[4] = 0x00;          /* only flush buffers supported */
539     else {
540         if (function) {
541             if (stp->flags & F_FM_WRITTEN)
542                 stp->flags &= ~F_DATA_WRITTEN;
543             else
544                 stp->flags |= F_FM_WRITTEN;
545         }
546     }
547     error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
548     if (error)
549         return error;
550     return ast_wait_dsc(dev, 10*60);
551 }
552
553 static int
554 ast_read_position(device_t dev, int hard, struct ast_readposition *position)
555 {
556     int8_t ccb[16] = { ATAPI_READ_POSITION, (hard ? 0x01 : 0), 0, 0, 0, 0, 0, 0,
557                        0, 0, 0, 0, 0, 0, 0, 0 };
558     int error;
559
560     error = ata_atapicmd(dev, ccb, (caddr_t)position, 
561                          sizeof(struct ast_readposition), ATA_R_READ, 10);
562     position->tape = ntohl(position->tape);
563     position->host = ntohl(position->host);
564     return error;
565 }
566
567 static int
568 ast_space(device_t dev, u_int8_t function, int32_t count)
569 {
570     int8_t ccb[16] = { ATAPI_SPACE, function, count>>16, count>>8, count,
571                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
572
573     return ata_atapicmd(dev, ccb, NULL, 0, 0, 60*60);
574 }
575
576 static int
577 ast_locate(device_t dev, int hard, u_int32_t pos)
578 {
579     int8_t ccb[16] = { ATAPI_LOCATE, 0x01 | (hard ? 0x4 : 0), 0,
580                        pos>>24, pos>>16, pos>>8, pos,
581                        0, 0, 0, 0, 0, 0, 0, 0, 0 };
582     int error;
583
584     error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
585     if (error)
586         return error;
587     return ast_wait_dsc(dev, 60*60);
588 }
589
590 static int
591 ast_prevent_allow(device_t dev, int lock)
592 {
593     int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
594                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
595
596     return ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
597 }
598
599 static int
600 ast_load_unload(device_t dev, u_int8_t function)
601 {
602     struct ast_softc *stp = device_get_ivars(dev);
603     int8_t ccb[16] = { ATAPI_START_STOP, 0x01, 0, 0, function, 0, 0, 0,
604                        0, 0, 0, 0, 0, 0, 0, 0 };
605     int error;
606
607     if ((function & ATAPI_SS_EJECT) && !stp->cap.eject)
608         return 0;
609     error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
610     if (error)
611         return error;
612     pause("astlu", 1 * hz);
613     if (function == ATAPI_SS_EJECT)
614         return 0;
615     return ast_wait_dsc(dev, 60*60);
616 }
617
618 static int
619 ast_rewind(device_t dev)
620 {
621     int8_t ccb[16] = { ATAPI_REZERO, 0x01, 0, 0, 0, 0, 0, 0,
622                        0, 0, 0, 0, 0, 0, 0, 0 };
623     int error;
624
625     error = ata_atapicmd(dev, ccb, NULL, 0, 0, 10);
626     if (error)
627         return error;
628     return ast_wait_dsc(dev, 60*60);
629 }
630
631 static int
632 ast_erase(device_t dev)
633 {
634     int8_t ccb[16] = { ATAPI_ERASE, 3, 0, 0, 0, 0, 0, 0,
635                        0, 0, 0, 0, 0, 0, 0, 0 };
636     int error;
637
638     if ((error = ast_rewind(dev)))
639         return error;
640
641     return ata_atapicmd(dev, ccb, NULL, 0, 0, 60*60);
642 }
643
644 static int
645 ast_test_ready(device_t dev)
646 {
647     int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
648                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
649
650     return ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
651 }
652
653 static int
654 ast_wait_dsc(device_t dev, int timeout)
655 {
656     int error = 0;
657     int8_t ccb[16] = { ATAPI_POLL_DSC, 0, 0, 0, 0,
658                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
659
660     timeout *= hz;
661     while (timeout > 0) {
662         error = ata_atapicmd(dev, ccb, NULL, 0, 0, 0);
663         if (error != EBUSY)
664             break;
665         pause("atpwt", hz / 2);
666         timeout -= (hz / 2);
667     }
668     return error;
669 }
670
671 static void 
672 ast_describe(device_t dev)
673 {
674     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
675     struct ata_device *atadev = device_get_softc(dev);
676     struct ast_softc *stp = device_get_ivars(dev);
677
678     if (bootverbose) {
679         device_printf(dev, "<%.40s/%.8s> tape drive at ata%d as %s\n",
680                       atadev->param.model, atadev->param.revision,
681                       device_get_unit(ch->dev),
682                       (atadev->unit == ATA_MASTER) ? "master" : "slave");
683         device_printf(dev, "%dKB/s, ", stp->cap.max_speed);
684         printf("transfer limit %d blk%s, ",
685                stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : "");
686         printf("%dKB buffer, ", (stp->cap.buffer_size * DEV_BSIZE) / 1024);
687         printf("%s\n", ata_mode2str(atadev->mode));
688         device_printf(dev, "Medium: ");
689         switch (stp->cap.medium_type) {
690             case 0x00:
691                 printf("none"); break;
692             case 0x17:
693                 printf("Travan 1 (400 Mbyte)"); break;
694             case 0xb6:
695                 printf("Travan 4 (4 Gbyte)"); break;
696             case 0xda:
697                 printf("OnStream ADR (15Gyte)"); break;
698             default:
699                 printf("unknown (0x%x)", stp->cap.medium_type);
700         }
701         if (stp->cap.readonly) printf(", readonly");
702         if (stp->cap.reverse) printf(", reverse");
703         if (stp->cap.eformat) printf(", eformat");
704         if (stp->cap.qfa) printf(", qfa");
705         if (stp->cap.lock) printf(", lock");
706         if (stp->cap.locked) printf(", locked");
707         if (stp->cap.prevent) printf(", prevent");
708         if (stp->cap.eject) printf(", eject");
709         if (stp->cap.disconnect) printf(", disconnect");
710         if (stp->cap.ecc) printf(", ecc");
711         if (stp->cap.compress) printf(", compress");
712         if (stp->cap.blk512) printf(", 512b");
713         if (stp->cap.blk1024) printf(", 1024b");
714         if (stp->cap.blk32k) printf(", 32kb");
715         printf("\n");
716     }
717     else {
718         device_printf(dev, "TAPE <%.40s/%.8s> at ata%d-%s %s\n",
719                       atadev->param.model, atadev->param.revision,
720                       device_get_unit(ch->dev),
721                       (atadev->unit == ATA_MASTER) ? "master" : "slave",
722                       ata_mode2str(atadev->mode));
723     }
724 }
725
726 static device_method_t ast_methods[] = {
727     /* device interface */
728     DEVMETHOD(device_probe,     ast_probe),
729     DEVMETHOD(device_attach,    ast_attach),
730     DEVMETHOD(device_detach,    ast_detach),
731     DEVMETHOD(device_shutdown,  ast_shutdown),
732                            
733     /* ATA methods */
734     DEVMETHOD(ata_reinit,       ast_reinit),
735
736     { 0, 0 }
737 };
738             
739 static driver_t ast_driver = {
740     "ast",
741     ast_methods,
742     0,
743 };
744
745 static devclass_t ast_devclass;
746
747 DRIVER_MODULE(ast, ata, ast_driver, ast_devclass, NULL, NULL);
748 MODULE_VERSION(ast, 1);
749 MODULE_DEPEND(ast, ata, 1, 1, 1);