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
29 * Copyright (c) 2002 Eric Moore
30 * Copyright (c) 2002 LSI Logic Corporation
31 * All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. The party using or redistributing the source code and binary forms
42 * agrees to the disclaimer below and the terms and conditions set forth
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * $FreeBSD: src/sys/dev/amr/amr_disk.c,v 1.39 2006/10/31 21:19:25 pjd Exp $
61 * Disk driver for AMI MegaRaid controllers
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/kernel.h>
67 #include <sys/module.h>
72 #include <sys/dtype.h>
76 #include <dev/raid/amr/amrio.h>
77 #include <dev/raid/amr/amrreg.h>
78 #include <dev/raid/amr/amrvar.h>
79 #include <dev/raid/amr/amr_tables.h>
82 static int amrd_probe(device_t dev
);
83 static int amrd_attach(device_t dev
);
84 static int amrd_detach(device_t dev
);
86 static d_open_t amrd_open
;
87 static d_strategy_t amrd_strategy
;
88 static d_dump_t amrd_dump
;
90 static struct dev_ops amrd_ops
= {
91 { "amrd", 0, D_DISK
},
93 .d_strategy
= amrd_strategy
,
97 static devclass_t amrd_devclass
;
99 static device_method_t amrd_methods
[] = {
100 DEVMETHOD(device_probe
, amrd_probe
),
101 DEVMETHOD(device_attach
, amrd_attach
),
102 DEVMETHOD(device_detach
, amrd_detach
),
106 static driver_t amrd_driver
= {
109 sizeof(struct amrd_softc
)
112 DRIVER_MODULE_ORDERED(amrd
, amr
, amrd_driver
, &amrd_devclass
, NULL
, NULL
,
116 amrd_open(struct dev_open_args
*ap
)
118 struct amrd_softc
*sc
= ap
->a_head
.a_dev
->si_drv1
;
125 /* controller not active? */
126 if (sc
->amrd_controller
->amr_state
& AMR_STATE_SHUTDOWN
)
131 /********************************************************************************
132 * System crashdump support
136 amrd_dump(struct dev_dump_args
*ap
)
138 cdev_t dev
= ap
->a_head
.a_dev
;
139 off_t offset
= ap
->a_offset
;
140 void *virtual = ap
->a_virtual
;
141 size_t length
= ap
->a_length
;
142 struct amrd_softc
*amrd_sc
;
143 struct amr_softc
*amr_sc
;
146 amrd_sc
= (struct amrd_softc
*)dev
->si_drv1
;
149 amr_sc
= (struct amr_softc
*)amrd_sc
->amrd_controller
;
152 int driveno
= amrd_sc
->amrd_drive
- amr_sc
->amr_drive
;
154 error
= amr_dump_blocks(amr_sc
, driveno
, offset
/ AMR_BLKSIZE
,
155 virtual, (int)length
/ AMR_BLKSIZE
);
161 * Read/write routine for a buffer. Finds the proper unit, range checks
162 * arguments, and schedules the transfer. Does not wait for the transfer
163 * to complete. Multi-page transfers are supported. All I/O requests must
164 * be a multiple of a sector in length.
167 amrd_strategy(struct dev_strategy_args
*ap
)
169 cdev_t dev
= ap
->a_head
.a_dev
;
170 struct bio
*bio
= ap
->a_bio
;
171 struct buf
*bp
= bio
->bio_buf
;
172 struct amrd_softc
*sc
= (struct amrd_softc
*)dev
->si_drv1
;
176 bp
->b_error
= EINVAL
;
179 bio
->bio_driver_info
= sc
;
181 devstat_start_transaction(&sc
->amrd_stats
);
182 amr_submit_bio(sc
->amrd_controller
, bio
);
186 bp
->b_flags
|= B_ERROR
;
189 * Correctly set the buf to indicate a completed transfer
191 bp
->b_resid
= bp
->b_bcount
;
197 amrd_intr(void *data
)
199 struct bio
*bio
= (struct bio
*)data
;
200 struct buf
*bp
= bio
->bio_buf
;
201 struct amrd_softc
*sc
= (struct amrd_softc
*)bio
->bio_driver_info
;
205 devstat_end_transaction_buf(&sc
->amrd_stats
, bp
);
206 if (bp
->b_flags
& B_ERROR
) {
208 debug(1, "i/o error\n");
217 amrd_probe(device_t dev
)
222 device_set_desc(dev
, "LSILogic MegaRAID logical drive");
227 amrd_attach(device_t dev
)
229 struct amrd_softc
*sc
= (struct amrd_softc
*)device_get_softc(dev
);
231 struct disk_info info
;
235 parent
= device_get_parent(dev
);
236 sc
->amrd_controller
= (struct amr_softc
*)device_get_softc(parent
);
237 sc
->amrd_unit
= device_get_unit(dev
);
238 sc
->amrd_drive
= device_get_ivars(dev
);
241 device_printf(dev
, "%uMB (%u sectors) RAID %d (%s)\n",
242 sc
->amrd_drive
->al_size
/ ((1024 * 1024) / AMR_BLKSIZE
),
243 sc
->amrd_drive
->al_size
, sc
->amrd_drive
->al_properties
& AMR_DRV_RAID_MASK
,
244 amr_describe_code(amr_table_drvstate
, AMR_DRV_CURSTATE(sc
->amrd_drive
->al_state
)));
246 devstat_add_entry(&sc
->amrd_stats
, "amrd", sc
->amrd_unit
, AMR_BLKSIZE
,
247 DEVSTAT_NO_ORDERED_TAGS
,
248 DEVSTAT_TYPE_STORARRAY
| DEVSTAT_TYPE_IF_OTHER
,
249 DEVSTAT_PRIORITY_ARRAY
);
251 sc
->amrd_dev_t
= disk_create(sc
->amrd_unit
, &sc
->amrd_disk
, &amrd_ops
);
252 sc
->amrd_dev_t
->si_drv1
= sc
;
254 /* set maximum I/O size to match the maximum s/g size */
255 sc
->amrd_dev_t
->si_iosize_max
= (AMR_NSEG
- 1) * PAGE_SIZE
;
258 * Set disk info, as it appears that all needed data is available already.
259 * Setting the disk info will also cause the probing to start.
261 bzero(&info
, sizeof(info
));
262 info
.d_media_blksize
= AMR_BLKSIZE
; /* optional */
263 info
.d_media_blocks
= sc
->amrd_drive
->al_size
;
265 info
.d_type
= DTYPE_SCSI
; /* mandatory */
266 info
.d_secpertrack
= sc
->amrd_drive
->al_sectors
;
267 info
.d_nheads
= sc
->amrd_drive
->al_heads
;
268 info
.d_ncylinders
= sc
->amrd_drive
->al_cylinders
;
269 info
.d_secpercyl
= sc
->amrd_drive
->al_sectors
* sc
->amrd_drive
->al_heads
;
271 disk_setdiskinfo(&sc
->amrd_disk
, &info
);
277 amrd_detach(device_t dev
)
279 struct amrd_softc
*sc
= (struct amrd_softc
*)device_get_softc(dev
);
283 #if 0 /* XXX swildner */
284 if (sc
->amrd_disk
->d_flags
& DISKFLAG_OPEN
)
288 devstat_remove_entry(&sc
->amrd_stats
);
289 disk_destroy(&sc
->amrd_disk
);