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