2 * Copyright (c) 1999 Jonathan Lemon
3 * Copyright (c) 1999, 2000 Michael Smith
4 * Copyright (c) 2000 BSDi
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * Copyright (c) 2002 Eric Moore
29 * Copyright (c) 2002 LSI Logic Corporation
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. The party using or redistributing the source code and binary forms
41 * agrees to the disclaimer below and the terms and conditions set forth
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * $FreeBSD: src/sys/dev/amr/amr_disk.c,v 1.5.2.5 2002/12/20 15:12:04 emoore Exp $
57 * $DragonFly: src/sys/dev/raid/amr/amr_disk.c,v 1.15 2007/06/17 23:50:16 dillon Exp $
61 * Disk driver for AMI MegaRaid controllers
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/kernel.h>
68 #include "amr_compat.h"
71 #include <sys/devicestat.h>
73 #include <sys/dtype.h>
79 #include <machine/md_var.h>
84 #include "amr_tables.h"
87 static int amrd_probe(device_t dev
);
88 static int amrd_attach(device_t dev
);
89 static int amrd_detach(device_t dev
);
91 static d_open_t amrd_open
;
92 static d_close_t amrd_close
;
93 static d_strategy_t amrd_strategy
;
94 static d_ioctl_t amrd_ioctl
;
95 static d_dump_t amrd_dump
;
97 #define AMRD_CDEV_MAJOR 133
99 static struct dev_ops amrd_ops
= {
100 { "amrd", AMRD_CDEV_MAJOR
, D_DISK
},
102 .d_close
= amrd_close
,
104 .d_write
= physwrite
,
105 .d_ioctl
= amrd_ioctl
,
106 .d_strategy
= amrd_strategy
,
110 static devclass_t amrd_devclass
;
112 static device_method_t amrd_methods
[] = {
113 DEVMETHOD(device_probe
, amrd_probe
),
114 DEVMETHOD(device_attach
, amrd_attach
),
115 DEVMETHOD(device_detach
, amrd_detach
),
119 static driver_t amrd_driver
= {
122 sizeof(struct amrd_softc
)
125 DRIVER_MODULE(amrd
, amr
, amrd_driver
, amrd_devclass
, 0, 0);
128 amrd_open(struct dev_open_args
*ap
)
130 cdev_t dev
= ap
->a_head
.a_dev
;
131 struct amrd_softc
*sc
= (struct amrd_softc
*)dev
->si_drv1
;
132 struct disk_info info
;
139 /* controller not active? */
140 if (sc
->amrd_controller
->amr_state
& AMR_STATE_SHUTDOWN
)
143 bzero(&info
, sizeof(info
));
144 info
.d_media_blksize
= AMR_BLKSIZE
; /* optional */
145 info
.d_media_blocks
= sc
->amrd_drive
->al_size
;
147 info
.d_type
= DTYPE_SCSI
; /* mandatory */
148 info
.d_secpertrack
= sc
->amrd_drive
->al_sectors
;
149 info
.d_nheads
= sc
->amrd_drive
->al_heads
;
150 info
.d_ncylinders
= sc
->amrd_drive
->al_cylinders
;
151 info
.d_secpercyl
= sc
->amrd_drive
->al_sectors
* sc
->amrd_drive
->al_heads
;
153 disk_setdiskinfo(&sc
->amrd_disk
, &info
);
155 sc
->amrd_flags
|= AMRD_OPEN
;
160 amrd_close(struct dev_close_args
*ap
)
162 cdev_t dev
= ap
->a_head
.a_dev
;
163 struct amrd_softc
*sc
= (struct amrd_softc
*)dev
->si_drv1
;
169 sc
->amrd_flags
&= ~AMRD_OPEN
;
174 amrd_ioctl(struct dev_ioctl_args
*ap
)
180 /********************************************************************************
181 * System crashdump support
184 amrd_dump(struct dev_dump_args
*ap
)
186 cdev_t dev
= ap
->a_head
.a_dev
;
187 struct amrd_softc
*amrd_sc
= (struct amrd_softc
*)dev
->si_drv1
;
188 struct amr_softc
*amr_sc
;
191 int dumppages
= MAXDUMPPGS
;
198 amr_sc
= (struct amr_softc
*)amrd_sc
->amrd_controller
;
200 if (!amrd_sc
|| !amr_sc
)
203 blkcnt
= howmany(PAGE_SIZE
, ap
->a_secsize
);
205 driveno
= amrd_sc
->amrd_drive
- amr_sc
->amr_drive
;
207 while (ap
->a_count
> 0) {
210 if ((ap
->a_count
/ blkcnt
) < dumppages
)
211 dumppages
= ap
->a_count
/ blkcnt
;
213 for (i
= 0; i
< dumppages
; ++i
) {
214 vm_paddr_t a
= addr
+ (i
* PAGE_SIZE
);
215 if (is_physical_memory(a
))
216 va
= pmap_kenter_temporary(trunc_page(a
), i
);
218 va
= pmap_kenter_temporary(trunc_page(0), i
);
221 if ((error
= amr_dump_blocks(amr_sc
, driveno
, ap
->a_blkno
, (void *)va
,
222 (PAGE_SIZE
* dumppages
) / AMR_BLKSIZE
)) != 0)
225 if (dumpstatus(addr
, (off_t
)ap
->a_count
* DEV_BSIZE
) < 0)
228 ap
->a_blkno
+= blkcnt
* dumppages
;
229 ap
->a_count
-= blkcnt
* dumppages
;
230 addr
+= PAGE_SIZE
* dumppages
;
235 * Read/write routine for a buffer. Finds the proper unit, range checks
236 * arguments, and schedules the transfer. Does not wait for the transfer
237 * to complete. Multi-page transfers are supported. All I/O requests must
238 * be a multiple of a sector in length.
241 amrd_strategy(struct dev_strategy_args
*ap
)
243 cdev_t dev
= ap
->a_head
.a_dev
;
244 struct bio
*bio
= ap
->a_bio
;
245 struct buf
*bp
= bio
->bio_buf
;
246 struct amrd_softc
*sc
= (struct amrd_softc
*)dev
->si_drv1
;
250 bp
->b_error
= EINVAL
;
253 bio
->bio_driver_info
= sc
;
255 devstat_start_transaction(&sc
->amrd_stats
);
256 amr_submit_bio(sc
->amrd_controller
, bio
);
260 bp
->b_flags
|= B_ERROR
;
263 * Correctly set the buf to indicate a completed transfer
265 bp
->b_resid
= bp
->b_bcount
;
271 amrd_intr(struct bio
*bio
)
273 struct buf
*bp
= bio
->bio_buf
;
277 if (bp
->b_flags
& B_ERROR
) {
279 debug(1, "i/o error\n");
287 amrd_probe(device_t dev
)
292 device_set_desc(dev
, "LSILogic MegaRAID logical drive");
297 amrd_attach(device_t dev
)
299 struct amrd_softc
*sc
= (struct amrd_softc
*)device_get_softc(dev
);
304 parent
= device_get_parent(dev
);
305 sc
->amrd_controller
= (struct amr_softc
*)device_get_softc(parent
);
306 sc
->amrd_unit
= device_get_unit(dev
);
307 sc
->amrd_drive
= device_get_ivars(dev
);
310 device_printf(dev
, "%uMB (%u sectors) RAID %d (%s)\n",
311 sc
->amrd_drive
->al_size
/ ((1024 * 1024) / AMR_BLKSIZE
),
312 sc
->amrd_drive
->al_size
, sc
->amrd_drive
->al_properties
& AMR_DRV_RAID_MASK
,
313 amr_describe_code(amr_table_drvstate
, AMR_DRV_CURSTATE(sc
->amrd_drive
->al_state
)));
315 devstat_add_entry(&sc
->amrd_stats
, "amrd", sc
->amrd_unit
, AMR_BLKSIZE
,
316 DEVSTAT_NO_ORDERED_TAGS
,
317 DEVSTAT_TYPE_STORARRAY
| DEVSTAT_TYPE_IF_OTHER
,
318 DEVSTAT_PRIORITY_ARRAY
);
320 sc
->amrd_dev_t
= disk_create(sc
->amrd_unit
, &sc
->amrd_disk
, &amrd_ops
);
321 sc
->amrd_dev_t
->si_drv1
= sc
;
323 /* set maximum I/O size to match the maximum s/g size */
324 sc
->amrd_dev_t
->si_iosize_max
= (AMR_NSEG
- 1) * PAGE_SIZE
;
330 amrd_detach(device_t dev
)
332 struct amrd_softc
*sc
= (struct amrd_softc
*)device_get_softc(dev
);
336 if (sc
->amrd_flags
& AMRD_OPEN
)
339 devstat_remove_entry(&sc
->amrd_stats
);
340 disk_destroy(&sc
->amrd_disk
);