2 * Copyright (c) 2000 Michael Smith
3 * Copyright (c) 2001 Scott Long
4 * Copyright (c) 2000 BSDi
5 * Copyright (c) 2001 Adaptec, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $FreeBSD: src/sys/dev/aac/aac_disk.c,v 1.3.2.8 2003/01/11 18:39:39 scottl Exp $
30 * $DragonFly: src/sys/dev/raid/aac/aac_disk.c,v 1.17 2007/05/15 00:01:04 dillon Exp $
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/sysctl.h>
40 #include "aac_compat.h"
43 #include <sys/devicestat.h>
50 #include <machine/md_var.h>
53 #include "aac_ioctl.h"
57 * Interface to parent.
59 static int aac_disk_probe(device_t dev
);
60 static int aac_disk_attach(device_t dev
);
61 static int aac_disk_detach(device_t dev
);
64 * Interface to the device switch.
66 static d_open_t aac_disk_open
;
67 static d_close_t aac_disk_close
;
68 static d_strategy_t aac_disk_strategy
;
69 static d_dump_t aac_disk_dump
;
71 #define AAC_DISK_CDEV_MAJOR 151
73 static struct dev_ops aac_disk_ops
= {
74 { "aacd", AAC_DISK_CDEV_MAJOR
, D_DISK
},
75 .d_open
= aac_disk_open
,
76 .d_close
= aac_disk_close
,
79 .d_strategy
= aac_disk_strategy
,
80 .d_dump
= aac_disk_dump
,
83 devclass_t aac_disk_devclass
;
85 static device_method_t aac_disk_methods
[] = {
86 DEVMETHOD(device_probe
, aac_disk_probe
),
87 DEVMETHOD(device_attach
, aac_disk_attach
),
88 DEVMETHOD(device_detach
, aac_disk_detach
),
92 static driver_t aac_disk_driver
= {
95 sizeof(struct aac_disk
)
98 #define AAC_MAXIO 65536
100 DRIVER_MODULE(aacd
, aac
, aac_disk_driver
, aac_disk_devclass
, 0, 0);
102 /* sysctl tunables */
103 static unsigned int aac_iosize_max
= AAC_MAXIO
; /* due to limits of the card */
104 TUNABLE_INT("hw.aac.iosize_max", &aac_iosize_max
);
106 SYSCTL_DECL(_hw_aac
);
107 SYSCTL_UINT(_hw_aac
, OID_AUTO
, iosize_max
, CTLFLAG_RD
, &aac_iosize_max
, 0,
108 "Max I/O size per transfer to an array");
111 * Handle open from generic layer.
113 * This is called by the diskslice code on first open in order to get the
114 * basic device geometry paramters.
117 aac_disk_open(struct dev_open_args
*ap
)
119 cdev_t dev
= ap
->a_head
.a_dev
;
121 struct disk_info info
;
125 sc
= (struct aac_disk
*)dev
->si_drv1
;
128 kprintf("aac_disk_open: No Softc\n");
132 /* check that the controller is up and running */
133 if (sc
->ad_controller
->aac_state
& AAC_STATE_SUSPEND
) {
134 kprintf("Controller Suspended controller state = 0x%x\n",
135 sc
->ad_controller
->aac_state
);
139 /* build synthetic label */
140 bzero(&info
, sizeof(info
));
141 info
.d_media_blksize
= AAC_BLOCK_SIZE
; /* mandatory */
142 info
.d_media_blocks
= sc
->ad_size
;
144 info
.d_type
= DTYPE_ESDI
; /* optional */
145 info
.d_secpertrack
= sc
->ad_sectors
;
146 info
.d_nheads
= sc
->ad_heads
;
147 info
.d_ncylinders
= sc
->ad_cylinders
;
148 info
.d_secpercyl
= sc
->ad_sectors
* sc
->ad_heads
;
150 disk_setdiskinfo(&sc
->ad_disk
, &info
);
151 sc
->ad_flags
|= AAC_DISK_OPEN
;
156 * Handle last close of the disk device.
159 aac_disk_close(struct dev_close_args
*ap
)
161 cdev_t dev
= ap
->a_head
.a_dev
;
166 sc
= (struct aac_disk
*)dev
->si_drv1
;
171 sc
->ad_flags
&= ~AAC_DISK_OPEN
;
176 * Handle an I/O request.
179 aac_disk_strategy(struct dev_strategy_args
*ap
)
181 cdev_t dev
= ap
->a_head
.a_dev
;
182 struct bio
*bio
= ap
->a_bio
;
183 struct buf
*bp
= bio
->bio_buf
;
188 sc
= (struct aac_disk
*)dev
->si_drv1
;
192 bp
->b_flags
|= B_ERROR
;
193 bp
->b_error
= EINVAL
;
198 /* do-nothing operation? */
199 if (bp
->b_bcount
== 0) {
200 bp
->b_resid
= bp
->b_bcount
;
205 /* perform accounting */
206 devstat_start_transaction(&sc
->ad_stats
);
208 /* pass the bio to the controller - it can work out who we are */
209 aac_submit_bio(sc
, bio
);
214 * Dump memory out to an array
216 * This queues blocks of memory of size AAC_MAXIO to the controller and waits
217 * for the controller to complete the requests.
220 aac_disk_dump(struct dev_dump_args
*ap
)
222 cdev_t dev
= ap
->a_head
.a_dev
;
224 struct aac_softc
*sc
;
232 dumppages
= AAC_MAXIO
/ PAGE_SIZE
;
237 sc
= ad
->ad_controller
;
239 blkcnt
= howmany(PAGE_SIZE
, ap
->a_secsize
);
241 while (ap
->a_count
> 0) {
244 if ((ap
->a_count
/ blkcnt
) < dumppages
)
245 dumppages
= ap
->a_count
/ blkcnt
;
247 for (i
= 0; i
< dumppages
; ++i
) {
248 vm_offset_t a
= addr
+ (i
* PAGE_SIZE
);
249 if (is_physical_memory(a
)) {
250 va
= pmap_kenter_temporary(trunc_page(a
), i
);
252 va
= pmap_kenter_temporary(trunc_page(0), i
);
258 * Queue the block to the controller. If the queue is full,
259 * EBUSY will be returned.
261 error
= aac_dump_enqueue(ad
, ap
->a_blkno
, va
, dumppages
);
262 if (error
&& (error
!= EBUSY
))
266 if (dumpstatus(addr
, (off_t
)(ap
->a_count
* DEV_BSIZE
)) < 0)
269 ap
->a_blkno
+= blkcnt
* dumppages
;
270 ap
->a_count
-= blkcnt
* dumppages
;
271 addr
+= PAGE_SIZE
* dumppages
;
277 * Either the queue was full on the last attemp, or we have no
278 * more data to dump. Let the queue drain out and retry the
279 * block if the queue was full.
281 aac_dump_complete(sc
);
291 * Handle completion of an I/O request.
294 aac_biodone(struct bio
*bio
, const char *code
)
296 struct buf
*bp
= bio
->bio_buf
;
301 sc
= (struct aac_disk
*)bio
->bio_driver_info
;
303 devstat_end_transaction_buf(&sc
->ad_stats
, bp
);
304 if (bp
->b_flags
& B_ERROR
) {
305 diskerr(bio
, sc
->ad_dev_t
,
315 aac_disk_probe(device_t dev
)
324 * Attach a unit to the controller.
327 aac_disk_attach(device_t dev
)
333 sc
= (struct aac_disk
*)device_get_softc(dev
);
335 /* initialise our softc */
337 (struct aac_softc
*)device_get_softc(device_get_parent(dev
));
338 sc
->ad_container
= device_get_ivars(dev
);
342 * require that extended translation be enabled - other drivers read the
345 sc
->ad_size
= sc
->ad_container
->co_mntobj
.Capacity
;
346 if (sc
->ad_size
>= (2 * 1024 * 1024)) { /* 2GB */
349 } else if (sc
->ad_size
>= (1 * 1024 * 1024)) { /* 1GB */
356 sc
->ad_cylinders
= (sc
->ad_size
/ (sc
->ad_heads
* sc
->ad_sectors
));
358 device_printf(dev
, "%uMB (%u sectors)\n",
359 sc
->ad_size
/ ((1024 * 1024) / AAC_BLOCK_SIZE
),
362 devstat_add_entry(&sc
->ad_stats
, "aacd", device_get_unit(dev
),
363 AAC_BLOCK_SIZE
, DEVSTAT_NO_ORDERED_TAGS
,
364 DEVSTAT_TYPE_STORARRAY
| DEVSTAT_TYPE_IF_OTHER
,
365 DEVSTAT_PRIORITY_ARRAY
);
367 /* attach a generic disk device to ourselves */
368 sc
->ad_dev_t
= disk_create(device_get_unit(dev
), &sc
->ad_disk
,
370 sc
->ad_dev_t
->si_drv1
= sc
;
372 sc
->ad_dev_t
->si_iosize_max
= aac_iosize_max
;
373 sc
->unit
= device_get_unit(dev
);
379 * Disconnect ourselves from the system.
382 aac_disk_detach(device_t dev
)
388 sc
= (struct aac_disk
*)device_get_softc(dev
);
390 if (sc
->ad_flags
& AAC_DISK_OPEN
)
393 devstat_remove_entry(&sc
->ad_stats
);
394 disk_destroy(&sc
->ad_disk
);