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