]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/amr/amr_disk.c
sfxge(4): unify power of 2 alignment check macro
[FreeBSD/FreeBSD.git] / sys / dev / amr / amr_disk.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1999 Jonathan Lemon
5  * Copyright (c) 1999, 2000 Michael Smith
6  * Copyright (c) 2000 BSDi
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 /*-
31  * Copyright (c) 2002 Eric Moore
32  * Copyright (c) 2002 LSI Logic Corporation
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  * 3. The party using or redistributing the source code and binary forms
44  *    agrees to the disclaimer below and the terms and conditions set forth
45  *    herein.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57  * SUCH DAMAGE.
58  */
59
60 #include <sys/cdefs.h>
61 __FBSDID("$FreeBSD$");
62
63 /*
64  * Disk driver for AMI MegaRaid controllers
65  */
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/kernel.h>
70 #include <sys/module.h>
71
72 #include <sys/bio.h>
73 #include <sys/bus.h>
74 #include <sys/conf.h>
75
76 #include <machine/bus.h>
77 #include <sys/rman.h>
78
79 #include <dev/amr/amrio.h>
80 #include <dev/amr/amrreg.h>
81 #include <dev/amr/amrvar.h>
82 #include <dev/amr/amr_tables.h>
83
84 /* prototypes */
85 static int amrd_probe(device_t dev);
86 static int amrd_attach(device_t dev);
87 static int amrd_detach(device_t dev);
88
89 static  disk_open_t     amrd_open;
90 static  disk_strategy_t amrd_strategy;
91
92 static devclass_t       amrd_devclass;
93 #ifdef FREEBSD_4
94 int                     amr_disks_registered = 0;
95 #endif
96
97 static device_method_t amrd_methods[] = {
98     DEVMETHOD(device_probe,     amrd_probe),
99     DEVMETHOD(device_attach,    amrd_attach),
100     DEVMETHOD(device_detach,    amrd_detach),
101     { 0, 0 }
102 };
103
104 static driver_t amrd_driver = {
105     "amrd",
106     amrd_methods,
107     sizeof(struct amrd_softc)
108 };
109
110 DRIVER_MODULE(amrd, amr, amrd_driver, amrd_devclass, 0, 0);
111
112 static int
113 amrd_open(struct disk *dp)
114 {
115     struct amrd_softc   *sc = (struct amrd_softc *)dp->d_drv1;
116
117     debug_called(1);
118
119     if (sc == NULL)
120         return (ENXIO);
121
122     /* controller not active? */
123     if (sc->amrd_controller->amr_state & AMR_STATE_SHUTDOWN)
124         return(ENXIO);
125
126     return (0);
127 }
128 /********************************************************************************
129  * System crashdump support
130  */
131
132 static int
133 amrd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
134 {
135
136     struct amrd_softc   *amrd_sc;
137     struct amr_softc    *amr_sc;
138     int                 error;
139     struct disk         *dp;
140
141     dp = arg;
142     amrd_sc = (struct amrd_softc *)dp->d_drv1;
143     if (amrd_sc == NULL)
144         return(ENXIO);
145     amr_sc  = (struct amr_softc *)amrd_sc->amrd_controller;
146
147     if (length > 0) {
148         int     driveno = amrd_sc->amrd_drive - amr_sc->amr_drive;
149         if ((error = amr_dump_blocks(amr_sc,driveno,offset / AMR_BLKSIZE ,(void *)virtual,(int) length / AMR_BLKSIZE  )) != 0)
150                 return(error);
151
152     }
153     return(0);
154 }
155
156 /*
157  * Read/write routine for a buffer.  Finds the proper unit, range checks
158  * arguments, and schedules the transfer.  Does not wait for the transfer
159  * to complete.  Multi-page transfers are supported.  All I/O requests must
160  * be a multiple of a sector in length.
161  */
162 static void
163 amrd_strategy(struct bio *bio)
164 {
165     struct amrd_softc   *sc = (struct amrd_softc *)bio->bio_disk->d_drv1;
166
167     /* bogus disk? */
168     if (sc == NULL) {
169         bio->bio_error = EINVAL;
170         goto bad;
171     }
172
173     amr_submit_bio(sc->amrd_controller, bio);
174     return;
175
176  bad:
177     bio->bio_flags |= BIO_ERROR;
178
179     /*
180      * Correctly set the buf to indicate a completed transfer
181      */
182     bio->bio_resid = bio->bio_bcount;
183     biodone(bio);
184     return;
185 }
186
187 void
188 amrd_intr(void *data)
189 {
190     struct bio *bio = (struct bio *)data;
191
192     debug_called(2);
193
194     if (bio->bio_flags & BIO_ERROR) {
195         bio->bio_error = EIO;
196         debug(1, "i/o error\n");
197     } else {
198         bio->bio_resid = 0;
199     }
200
201     biodone(bio);
202 }
203
204 static int
205 amrd_probe(device_t dev)
206 {
207
208     debug_called(1);
209
210     device_set_desc(dev, "LSILogic MegaRAID logical drive");
211     return (0);
212 }
213
214 static int
215 amrd_attach(device_t dev)
216 {
217     struct amrd_softc   *sc = (struct amrd_softc *)device_get_softc(dev);
218     device_t            parent;
219     
220     debug_called(1);
221
222     parent = device_get_parent(dev);
223     sc->amrd_controller = (struct amr_softc *)device_get_softc(parent);
224     sc->amrd_unit = device_get_unit(dev);
225     sc->amrd_drive = device_get_ivars(dev);
226     sc->amrd_dev = dev;
227
228     device_printf(dev, "%uMB (%u sectors) RAID %d (%s)\n",
229                   sc->amrd_drive->al_size / ((1024 * 1024) / AMR_BLKSIZE),
230                   sc->amrd_drive->al_size, sc->amrd_drive->al_properties & AMR_DRV_RAID_MASK, 
231                   amr_describe_code(amr_table_drvstate, AMR_DRV_CURSTATE(sc->amrd_drive->al_state)));
232
233     sc->amrd_disk = disk_alloc();
234     sc->amrd_disk->d_drv1 = sc;
235     sc->amrd_disk->d_maxsize = (AMR_NSEG - 1) * PAGE_SIZE;
236     sc->amrd_disk->d_open = amrd_open;
237     sc->amrd_disk->d_strategy = amrd_strategy;
238     sc->amrd_disk->d_name = "amrd";
239     sc->amrd_disk->d_dump = (dumper_t *)amrd_dump;
240     sc->amrd_disk->d_unit = sc->amrd_unit;
241     sc->amrd_disk->d_flags = DISKFLAG_CANFLUSHCACHE;
242     sc->amrd_disk->d_sectorsize = AMR_BLKSIZE;
243     sc->amrd_disk->d_mediasize = (off_t)sc->amrd_drive->al_size * AMR_BLKSIZE;
244     sc->amrd_disk->d_fwsectors = sc->amrd_drive->al_sectors;
245     sc->amrd_disk->d_fwheads = sc->amrd_drive->al_heads;
246     disk_create(sc->amrd_disk, DISK_VERSION);
247
248     return (0);
249 }
250
251 static int
252 amrd_detach(device_t dev)
253 {
254     struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev);
255
256     debug_called(1);
257
258     if (sc->amrd_disk->d_flags & DISKFLAG_OPEN)
259         return(EBUSY);
260
261 #ifdef FREEBSD_4
262     if (--amr_disks_registered == 0)
263         cdevsw_remove(&amrddisk_cdevsw);
264 #else
265     disk_destroy(sc->amrd_disk);
266 #endif
267     return(0);
268 }
269