2 * Copyright (c) 1998 - 2006 Søren Schmidt <sos@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
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.
26 * $FreeBSD: src/sys/dev/ata/atapi-fd.c,v 1.109 2006/03/30 05:29:57 marcel Exp $
27 * $DragonFly: src/sys/dev/disk/nata/atapi-fd.c,v 1.4.6.1 2008/09/25 01:44:55 dillon Exp $
30 #include <sys/param.h>
35 #include <sys/device.h>
36 #include <sys/devicestat.h>
38 #include <sys/endian.h>
39 #include <sys/kernel.h>
40 #include <sys/libkern.h>
41 #include <sys/malloc.h>
42 #include <sys/module.h>
44 #include <sys/systm.h>
50 /* device structure */
51 static d_open_t afd_open
;
52 static d_close_t afd_close
;
53 static d_ioctl_t afd_ioctl
;
54 static d_strategy_t afd_strategy
;
55 static struct dev_ops afd_ops
= {
56 { "afd", 118, D_DISK
| D_TRACKCLOSE
},
62 .d_strategy
= afd_strategy
,
66 static int afd_sense(device_t
);
67 static void afd_describe(device_t
);
68 static void afd_done(struct ata_request
*);
69 static int afd_prevent_allow(device_t
, int);
70 static int afd_test_ready(device_t
);
73 static MALLOC_DEFINE(M_AFD
, "afd_driver", "ATAPI floppy driver buffers");
76 afd_probe(device_t dev
)
78 struct ata_device
*atadev
= device_get_softc(dev
);
79 if ((atadev
->param
.config
& ATA_PROTO_ATAPI
) &&
80 (atadev
->param
.config
& ATA_ATAPI_TYPE_MASK
) == ATA_ATAPI_TYPE_DIRECT
)
87 afd_attach(device_t dev
)
89 struct ata_channel
*ch
= device_get_softc(device_get_parent(dev
));
90 struct ata_device
*atadev
= device_get_softc(dev
);
91 struct afd_softc
*fdp
;
94 fdp
= kmalloc(sizeof(struct afd_softc
), M_AFD
, M_WAITOK
| M_ZERO
);
95 device_set_ivars(dev
, fdp
);
96 ATA_SETMODE(device_get_parent(dev
), dev
);
99 device_set_ivars(dev
, NULL
);
103 atadev
->flags
|= ATA_D_MEDIA_CHANGED
;
105 /* create the disk device */
106 devstat_add_entry(&fdp
->stats
, "afd", device_get_unit(dev
), DEV_BSIZE
,
107 DEVSTAT_NO_ORDERED_TAGS
, DEVSTAT_TYPE_DIRECT
|
108 DEVSTAT_TYPE_IF_IDE
, DEVSTAT_PRIORITY_WFD
);
109 cdev
= disk_create(device_get_unit(dev
), &fdp
->disk
, &afd_ops
);
112 cdev
->si_iosize_max
= ch
->dma
->max_iosize
;
114 cdev
->si_iosize_max
= DFLTPHYS
;
117 /* announce we are here */
123 afd_detach(device_t dev
)
125 struct afd_softc
*fdp
= device_get_ivars(dev
);
127 /* check that we have a valid device to detach */
128 if (!device_get_ivars(dev
))
131 /* detroy disk from the system so we dont get any further requests */
132 disk_invalidate(&fdp
->disk
);
133 disk_destroy(&fdp
->disk
);
135 /* fail requests on the queue and any thats "in flight" for this device */
136 ata_fail_requests(dev
);
138 /* dont leave anything behind */
139 /* disk_destroy() already took care of the dev_ops */
140 devstat_remove_entry(&fdp
->stats
);
141 device_set_ivars(dev
, NULL
);
147 afd_shutdown(device_t dev
)
149 struct ata_device
*atadev
= device_get_softc(dev
);
151 if (atadev
->param
.support
.command2
& ATA_SUPPORT_FLUSHCACHE
)
152 ata_controlcmd(dev
, ATA_FLUSHCACHE
, 0, 0, 0);
156 afd_reinit(device_t dev
)
158 struct ata_channel
*ch
= device_get_softc(device_get_parent(dev
));
159 struct ata_device
*atadev
= device_get_softc(dev
);
160 struct afd_softc
*fdp
= device_get_ivars(dev
);
162 if (((atadev
->unit
== ATA_MASTER
) && !(ch
->devices
& ATA_ATAPI_MASTER
)) ||
163 ((atadev
->unit
== ATA_SLAVE
) && !(ch
->devices
& ATA_ATAPI_SLAVE
))) {
164 device_set_ivars(dev
, NULL
);
168 ATA_SETMODE(device_get_parent(dev
), dev
);
173 afd_open(struct dev_open_args
*ap
)
175 device_t dev
= ap
->a_head
.a_dev
->si_drv1
;
176 struct ata_device
*atadev
= device_get_softc(dev
);
177 struct afd_softc
*fdp
= device_get_ivars(dev
);
178 struct disk_info info
;
182 if (!device_is_attached(dev
))
186 afd_prevent_allow(dev
, 1);
189 device_printf(dev
, "sense media type failed\n");
190 atadev
->flags
&= ~ATA_D_MEDIA_CHANGED
;
195 bzero(&info
, sizeof(info
));
196 info
.d_media_blksize
= fdp
->sectorsize
; /* mandatory */
197 info
.d_media_size
= fdp
->mediasize
; /* (this is in bytes) */
199 info
.d_secpertrack
= fdp
->sectors
; /* optional */
200 info
.d_nheads
= fdp
->heads
;
202 ((fdp
->mediasize
/fdp
->sectorsize
)/fdp
->sectors
)/fdp
->heads
;
203 info
.d_secpercyl
= fdp
->sectors
* fdp
->heads
;
205 disk_setdiskinfo(&fdp
->disk
, &info
);
210 afd_close(struct dev_close_args
*ap
)
212 device_t dev
= ap
->a_head
.a_dev
->si_drv1
;
213 struct afd_softc
*fdp
= device_get_ivars(dev
);
215 if (count_dev(fdp
->cdev
) == 1)
216 afd_prevent_allow(dev
, 0);
221 afd_ioctl(struct dev_ioctl_args
*ap
)
223 return ata_device_ioctl(ap
->a_head
.a_dev
->si_drv1
, ap
->a_cmd
, ap
->a_data
);
227 afd_strategy(struct dev_strategy_args
*ap
)
229 device_t dev
= ap
->a_head
.a_dev
->si_drv1
;
230 struct bio
*bp
= ap
->a_bio
;
231 struct buf
*bbp
= bp
->bio_buf
;
232 struct ata_device
*atadev
= device_get_softc(dev
);
233 struct afd_softc
*fdp
= device_get_ivars(dev
);
234 struct ata_request
*request
;
239 /* if it's a null transfer, return immediatly. */
240 if (bbp
->b_bcount
== 0) {
246 /* should reject all queued entries if media have changed. */
247 if (atadev
->flags
& ATA_D_MEDIA_CHANGED
) {
248 bbp
->b_flags
|= B_ERROR
;
254 lba
= bp
->bio_offset
/ fdp
->sectorsize
;
255 count
= bbp
->b_bcount
/ fdp
->sectorsize
;
256 bbp
->b_resid
= bbp
->b_bcount
;
258 bzero(ccb
, sizeof(ccb
));
262 ccb
[0] = ATAPI_READ_BIG
;
265 ccb
[0] = ATAPI_WRITE_BIG
;
268 device_printf(dev
, "unknown BUF operation\n");
269 bbp
->b_flags
|= B_ERROR
;
282 if (!(request
= ata_alloc_request())) {
283 bbp
->b_flags
|= B_ERROR
;
284 bbp
->b_error
= ENOMEM
;
290 bcopy(ccb
, request
->u
.atapi
.ccb
,
291 (atadev
->param
.config
& ATA_PROTO_MASK
) ==
292 ATA_PROTO_ATAPI_12
? 16 : 12);
293 request
->data
= bbp
->b_data
;
294 request
->bytecount
= count
* fdp
->sectorsize
;
295 request
->transfersize
= min(request
->bytecount
, 65534);
296 request
->timeout
= (ccb
[0] == ATAPI_WRITE_BIG
) ? 60 : 30;
297 request
->retries
= 2;
298 request
->callback
= afd_done
;
300 switch (bbp
->b_cmd
) {
302 request
->flags
= (ATA_R_ATAPI
| ATA_R_READ
);
305 request
->flags
= (ATA_R_ATAPI
| ATA_R_WRITE
);
310 if (atadev
->mode
>= ATA_DMA
)
311 request
->flags
|= ATA_R_DMA
;
312 request
->flags
|= ATA_R_ORDERED
;
313 devstat_start_transaction(&fdp
->stats
);
314 ata_queue_request(request
);
319 afd_done(struct ata_request
*request
)
321 struct afd_softc
*fdp
= device_get_ivars(request
->dev
);
322 struct bio
*bp
= request
->bio
;
323 struct buf
*bbp
= bp
->bio_buf
;
325 /* finish up transfer */
326 if ((bbp
->b_error
= request
->result
))
327 bbp
->b_flags
|= B_ERROR
;
328 bbp
->b_resid
= bbp
->b_bcount
- request
->donecount
;
329 devstat_end_transaction_buf(&fdp
->stats
, bbp
);
331 ata_free_request(request
);
335 afd_sense(device_t dev
)
337 struct ata_device
*atadev
= device_get_softc(dev
);
338 struct afd_softc
*fdp
= device_get_ivars(dev
);
339 struct afd_capacity capacity
;
340 struct afd_capacity_big capacity_big
;
341 struct afd_capabilities capabilities
;
342 int8_t ccb1
[16] = { ATAPI_READ_CAPACITY
, 0, 0, 0, 0, 0, 0, 0,
343 0, 0, 0, 0, 0, 0, 0, 0 };
344 int8_t ccb2
[16] = { ATAPI_SERVICE_ACTION_IN
, 0x10, 0, 0, 0, 0, 0, 0, 0, 0,
345 0, 0, 0, sizeof(struct afd_capacity_big
) & 0xff, 0, 0 };
346 int8_t ccb3
[16] = { ATAPI_MODE_SENSE_BIG
, 0, ATAPI_REWRITEABLE_CAP_PAGE
,
347 0, 0, 0, 0, sizeof(struct afd_capabilities
) >> 8,
348 sizeof(struct afd_capabilities
) & 0xff,
349 0, 0, 0, 0, 0, 0, 0 };
355 /* wait for device to get ready */
356 while ((error
= afd_test_ready(dev
)) && timeout
--) {
362 /* The IOMEGA Clik! doesn't support reading the cap page, fake it */
363 if (!strncmp(atadev
->param
.model
, "IOMEGA Clik!", 12)) {
366 fdp
->mediasize
= 39441 * 1024;
367 fdp
->sectorsize
= 512;
372 /* get drive capacity */
373 if (!ata_atapicmd(dev
, ccb1
, (caddr_t
)&capacity
,
374 sizeof(struct afd_capacity
), ATA_R_READ
, 30)) {
377 fdp
->sectorsize
= be32toh(capacity
.blocksize
);
378 fdp
->mediasize
= (u_int64_t
)be32toh(capacity
.capacity
)*fdp
->sectorsize
;
383 /* get drive capacity big */
384 if (!ata_atapicmd(dev
, ccb2
, (caddr_t
)&capacity_big
,
385 sizeof(struct afd_capacity_big
),
386 ATA_R_READ
| ATA_R_QUIET
, 30)) {
389 fdp
->sectorsize
= be32toh(capacity_big
.blocksize
);
390 fdp
->mediasize
= be64toh(capacity_big
.capacity
)*fdp
->sectorsize
;
395 /* get drive capabilities, some bugridden drives needs this repeated */
396 for (count
= 0 ; count
< 5 ; count
++) {
397 if (!ata_atapicmd(dev
, ccb3
, (caddr_t
)&capabilities
,
398 sizeof(struct afd_capabilities
), ATA_R_READ
, 30) &&
399 capabilities
.page_code
== ATAPI_REWRITEABLE_CAP_PAGE
) {
400 fdp
->heads
= capabilities
.heads
;
401 fdp
->sectors
= capabilities
.sectors
;
402 fdp
->sectorsize
= be16toh(capabilities
.sector_size
);
403 fdp
->mediasize
= be16toh(capabilities
.cylinders
) *
404 fdp
->heads
* fdp
->sectors
* fdp
->sectorsize
;
405 if (!capabilities
.medium_type
)
414 afd_prevent_allow(device_t dev
, int lock
)
416 struct ata_device
*atadev
= device_get_softc(dev
);
417 int8_t ccb
[16] = { ATAPI_PREVENT_ALLOW
, 0, 0, 0, lock
,
418 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
420 if (!strncmp(atadev
->param
.model
, "IOMEGA Clik!", 12))
422 return ata_atapicmd(dev
, ccb
, NULL
, 0, 0, 30);
426 afd_test_ready(device_t dev
)
428 int8_t ccb
[16] = { ATAPI_TEST_UNIT_READY
, 0, 0, 0, 0,
429 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
431 return ata_atapicmd(dev
, ccb
, NULL
, 0, 0, 30);
435 afd_describe(device_t dev
)
437 struct ata_channel
*ch
= device_get_softc(device_get_parent(dev
));
438 struct ata_device
*atadev
= device_get_softc(dev
);
439 struct afd_softc
*fdp
= device_get_ivars(dev
);
442 if (fdp
->mediasize
> 1048576 * 5)
443 ksprintf(sizestring
, "%lluMB", (unsigned long long)
444 (fdp
->mediasize
/ 1048576));
445 else if (fdp
->mediasize
)
446 ksprintf(sizestring
, "%lluKB", (unsigned long long)
447 (fdp
->mediasize
/ 1024));
449 strcpy(sizestring
, "(no media)");
451 device_printf(dev
, "%s <%.40s %.8s> at ata%d-%s %s\n",
452 sizestring
, atadev
->param
.model
, atadev
->param
.revision
,
453 device_get_unit(ch
->dev
),
454 (atadev
->unit
== ATA_MASTER
) ? "master" : "slave",
455 ata_mode2str(atadev
->mode
));
457 device_printf(dev
, "%llu sectors [%lluC/%dH/%dS]\n",
458 (unsigned long long)(fdp
->mediasize
/ fdp
->sectorsize
),
460 (fdp
->mediasize
/(fdp
->sectorsize
*fdp
->sectors
*fdp
->heads
)),
461 fdp
->heads
, fdp
->sectors
);
465 static device_method_t afd_methods
[] = {
466 /* device interface */
467 DEVMETHOD(device_probe
, afd_probe
),
468 DEVMETHOD(device_attach
, afd_attach
),
469 DEVMETHOD(device_detach
, afd_detach
),
470 DEVMETHOD(device_shutdown
, afd_shutdown
),
473 DEVMETHOD(ata_reinit
, afd_reinit
),
478 static driver_t afd_driver
= {
484 static devclass_t afd_devclass
;
486 DRIVER_MODULE(afd
, ata
, afd_driver
, afd_devclass
, NULL
, NULL
);
487 MODULE_VERSION(afd
, 1);
488 MODULE_DEPEND(afd
, ata
, 1, 1, 1);