2 * Copyright (c) 1998,1999,2000,2001,2002 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.
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.
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.
28 * $FreeBSD: src/sys/dev/ata/atapi-fd.c,v 1.44.2.9 2002/07/31 11:19:26 sos Exp $
31 #include <sys/param.h>
32 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
40 #include <sys/devicestat.h>
42 #include <dev/ata/ata-all.h>
43 #include <dev/ata/atapi-all.h>
44 #include <dev/ata/atapi-fd.h>
46 /* device structures */
47 static d_open_t afdopen;
48 static d_close_t afdclose;
49 static d_ioctl_t afdioctl;
50 static d_strategy_t afdstrategy;
51 static struct cdevsw afd_cdevsw = {
55 /* write */ physwrite,
59 /* strategy */ afdstrategy,
64 /* flags */ D_DISK | D_TRACKCLOSE,
66 static struct cdevsw afddisk_cdevsw;
69 static int afd_sense(struct afd_softc *);
70 static void afd_describe(struct afd_softc *);
71 static int afd_done(struct atapi_request *);
72 static int afd_eject(struct afd_softc *, int);
73 static int afd_start_stop(struct afd_softc *, int);
74 static int afd_prevent_allow(struct afd_softc *, int);
77 static u_int32_t afd_lun_map = 0;
78 static MALLOC_DEFINE(M_AFD, "AFD driver", "ATAPI floppy driver buffers");
81 afdattach(struct ata_device *atadev)
83 struct afd_softc *fdp;
86 fdp = malloc(sizeof(struct afd_softc), M_AFD, M_NOWAIT | M_ZERO);
88 ata_prtdev(atadev, "out of memory\n");
93 fdp->lun = ata_get_lun(&afd_lun_map);
94 ata_set_name(atadev, "afd", fdp->lun);
95 bufq_init(&fdp->queue);
102 devstat_add_entry(&fdp->stats, "afd", fdp->lun, DEV_BSIZE,
103 DEVSTAT_NO_ORDERED_TAGS,
104 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE,
105 DEVSTAT_PRIORITY_WFD);
106 dev = disk_create(fdp->lun, &fdp->disk, 0, &afd_cdevsw, &afddisk_cdevsw);
110 if (!strncmp(atadev->param->model, "IOMEGA ZIP", 10) ||
111 !strncmp(atadev->param->model, "IOMEGA Clik!", 12))
112 fdp->dev->si_iosize_max = 64 * DEV_BSIZE;
114 fdp->dev->si_iosize_max = 252 * DEV_BSIZE;
117 atadev->flags |= ATA_D_MEDIA_CHANGED;
118 atadev->driver = fdp;
123 afddetach(struct ata_device *atadev)
125 struct afd_softc *fdp = atadev->driver;
128 while ((bp = bufq_first(&fdp->queue))) {
129 bufq_remove(&fdp->queue, bp);
130 bp->b_flags |= B_ERROR;
134 disk_invalidate(&fdp->disk);
135 disk_destroy(fdp->dev);
136 devstat_remove_entry(&fdp->stats);
137 ata_free_name(atadev);
138 ata_free_lun(&afd_lun_map, fdp->lun);
140 atadev->driver = NULL;
144 afd_sense(struct afd_softc *fdp)
146 int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, ATAPI_REWRITEABLE_CAP_PAGE,
147 0, 0, 0, 0, sizeof(struct afd_cappage) >> 8,
148 sizeof(struct afd_cappage) & 0xff, 0, 0, 0, 0, 0, 0, 0 };
149 int count, error = 0;
151 /* The IOMEGA Clik! doesn't support reading the cap page, fake it */
152 if (!strncmp(fdp->device->param->model, "IOMEGA Clik!", 12)) {
153 fdp->cap.transfer_rate = 500;
155 fdp->cap.sectors = 2;
156 fdp->cap.cylinders = 39441;
157 fdp->cap.sector_size = 512;
158 atapi_test_ready(fdp->device);
162 /* get drive capabilities, some drives needs this repeated */
163 for (count = 0 ; count < 5 ; count++) {
164 if (!(error = atapi_queue_cmd(fdp->device, ccb, (caddr_t)&fdp->cap,
165 sizeof(struct afd_cappage),
166 ATPR_F_READ, 30, NULL, NULL)))
169 if (error || fdp->cap.page_code != ATAPI_REWRITEABLE_CAP_PAGE)
171 fdp->cap.cylinders = ntohs(fdp->cap.cylinders);
172 fdp->cap.sector_size = ntohs(fdp->cap.sector_size);
173 fdp->cap.transfer_rate = ntohs(fdp->cap.transfer_rate);
178 afd_describe(struct afd_softc *fdp)
181 ata_prtdev(fdp->device,
182 "<%.40s/%.8s> rewriteable drive at ata%d as %s\n",
183 fdp->device->param->model, fdp->device->param->revision,
184 device_get_unit(fdp->device->channel->dev),
185 (fdp->device->unit == ATA_MASTER) ? "master" : "slave");
186 ata_prtdev(fdp->device,
187 "%luMB (%u sectors), %u cyls, %u heads, %u S/T, %u B/S\n",
188 (fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors) /
189 ((1024L * 1024L) / fdp->cap.sector_size),
190 fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors,
191 fdp->cap.cylinders, fdp->cap.heads, fdp->cap.sectors,
192 fdp->cap.sector_size);
193 ata_prtdev(fdp->device, "%dKB/s,", fdp->lun, fdp->cap.transfer_rate/8);
194 printf(" %s\n", ata_mode2str(fdp->device->mode));
195 if (fdp->cap.medium_type) {
196 ata_prtdev(fdp->device, "Medium: ");
197 switch (fdp->cap.medium_type) {
199 printf("720KB DD disk"); break;
202 printf("1.2MB HD disk"); break;
205 printf("1.44MB HD disk"); break;
208 printf("120MB UHD disk"); break;
211 printf("Unknown (0x%x)", fdp->cap.medium_type);
213 if (fdp->cap.wp) printf(", writeprotected");
218 ata_prtdev(fdp->device, "%luMB <%.40s> [%d/%d/%d] at ata%d-%s %s\n",
219 (fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors) /
220 ((1024L * 1024L) / fdp->cap.sector_size),
221 fdp->device->param->model,
222 fdp->cap.cylinders, fdp->cap.heads, fdp->cap.sectors,
223 device_get_unit(fdp->device->channel->dev),
224 (fdp->device->unit == ATA_MASTER) ? "master" : "slave",
225 ata_mode2str(fdp->device->mode));
230 afdopen(dev_t dev, int flags, int fmt, struct proc *p)
232 struct afd_softc *fdp = dev->si_drv1;
233 struct disklabel *label = &fdp->disk.d_label;
235 atapi_test_ready(fdp->device);
237 if (count_dev(dev) == 1)
238 afd_prevent_allow(fdp, 1);
241 ata_prtdev(fdp->device, "sense media type failed\n");
243 fdp->device->flags &= ~ATA_D_MEDIA_CHANGED;
245 bzero(label, sizeof *label);
246 label->d_secsize = fdp->cap.sector_size;
247 label->d_nsectors = fdp->cap.sectors;
248 label->d_ntracks = fdp->cap.heads;
249 label->d_ncylinders = fdp->cap.cylinders;
250 label->d_secpercyl = fdp->cap.sectors * fdp->cap.heads;
251 label->d_secperunit = label->d_secpercyl * fdp->cap.cylinders;
256 afdclose(dev_t dev, int flags, int fmt, struct proc *p)
258 struct afd_softc *fdp = dev->si_drv1;
260 if (count_dev(dev) == 1)
261 afd_prevent_allow(fdp, 0);
266 afdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
268 struct afd_softc *fdp = dev->si_drv1;
272 if (count_dev(dev) > 1)
274 return afd_eject(fdp, 0);
277 if (count_dev(dev) > 1)
279 return afd_eject(fdp, 1);
287 afdstrategy(struct buf *bp)
289 struct afd_softc *fdp = bp->b_dev->si_drv1;
292 if (fdp->device->flags & ATA_D_DETACHING) {
293 bp->b_flags |= B_ERROR;
299 /* if it's a null transfer, return immediatly. */
300 if (bp->b_bcount == 0) {
307 bufqdisksort(&fdp->queue, bp);
309 ata_start(fdp->device->channel);
313 afd_start(struct ata_device *atadev)
315 struct afd_softc *fdp = atadev->driver;
316 struct buf *bp = bufq_first(&fdp->queue);
325 bufq_remove(&fdp->queue, bp);
327 /* should reject all queued entries if media have changed. */
328 if (fdp->device->flags & ATA_D_MEDIA_CHANGED) {
329 bp->b_flags |= B_ERROR;
336 count = bp->b_bcount / fdp->cap.sector_size;
337 data_ptr = bp->b_data;
338 bp->b_resid = bp->b_bcount;
340 bzero(ccb, sizeof(ccb));
342 if (bp->b_flags & B_READ)
343 ccb[0] = ATAPI_READ_BIG;
345 ccb[0] = ATAPI_WRITE_BIG;
354 devstat_start_transaction(&fdp->stats);
356 atapi_queue_cmd(fdp->device, ccb, data_ptr, count * fdp->cap.sector_size,
357 (bp->b_flags & B_READ) ? ATPR_F_READ : 0, 30,
362 afd_done(struct atapi_request *request)
364 struct buf *bp = request->driver;
365 struct afd_softc *fdp = request->device->driver;
367 if (request->error || (bp->b_flags & B_ERROR)) {
368 bp->b_error = request->error;
369 bp->b_flags |= B_ERROR;
372 bp->b_resid = bp->b_bcount - request->donecount;
373 devstat_end_transaction_buf(&fdp->stats, bp);
379 afd_eject(struct afd_softc *fdp, int close)
383 if ((error = afd_start_stop(fdp, 0)) == EBUSY) {
386 if ((error = afd_start_stop(fdp, 3)))
388 return afd_prevent_allow(fdp, 1);
394 if ((error = afd_prevent_allow(fdp, 0)))
396 fdp->device->flags |= ATA_D_MEDIA_CHANGED;
397 return afd_start_stop(fdp, 2);
401 afd_start_stop(struct afd_softc *fdp, int start)
403 int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
404 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
406 return atapi_queue_cmd(fdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);
410 afd_prevent_allow(struct afd_softc *fdp, int lock)
412 int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
415 if (!strncmp(fdp->device->param->model, "IOMEGA Clik!", 12))
417 return atapi_queue_cmd(fdp->device, ccb, NULL, 0, 0, 30, NULL, NULL);