2 * Copyright (c) 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/pst/pst-raid.c,v 1.2.2.1 2002/08/18 12:32:36 sos Exp $
29 * $DragonFly: src/sys/dev/raid/pst/pst-raid.c,v 1.25 2007/11/14 18:27:52 swildner Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
40 #include <sys/devicestat.h>
41 #include <sys/eventhandler.h>
42 #include <sys/malloc.h>
46 #include <sys/thread2.h>
51 #include <machine/stdarg.h>
53 #include <bus/pci/pcivar.h>
54 #include <bus/pci/pcireg.h>
58 /* device structures */
59 static d_strategy_t pststrategy
;
60 static struct dev_ops pst_ops
= {
61 { "pst", 168, D_DISK
},
66 .d_strategy
= pststrategy
,
70 struct iop_softc
*iop
;
71 struct i2o_lct_entry
*lct
;
72 struct i2o_bsa_device
*info
;
76 struct bio_queue_head bio_queue
;
81 struct pst_softc
*psc
; /* pointer to softc */
82 u_int32_t mfa
; /* frame address */
83 struct callout timeout
; /* callout handle */
84 struct bio
*bio
; /* associated bio ptr */
88 static int pst_probe(device_t
);
89 static int pst_attach(device_t
);
91 static int pst_shutdown(device_t
);
93 static void pst_start(struct pst_softc
*);
94 static void pst_done(struct iop_softc
*, u_int32_t
, struct i2o_single_reply
*);
95 static int pst_rw(struct pst_request
*);
96 static void pst_timeout(void *);
97 static void bpack(int8_t *, int8_t *, int);
100 static MALLOC_DEFINE(M_PSTRAID
, "pst", "Promise SuperTrak RAID driver");
103 pst_add_raid(struct iop_softc
*sc
, struct i2o_lct_entry
*lct
)
105 struct pst_softc
*psc
;
106 device_t child
= device_add_child(sc
->dev
, "pst", -1);
110 psc
= kmalloc(sizeof(struct pst_softc
), M_PSTRAID
, M_INTWAIT
| M_ZERO
);
113 device_set_softc(child
, psc
);
114 return bus_generic_attach(sc
->dev
);
118 pst_probe(device_t dev
)
120 device_set_desc(dev
, "Promise SuperTrak RAID");
125 pst_attach(device_t dev
)
127 struct pst_softc
*psc
= device_get_softc(dev
);
128 struct i2o_get_param_reply
*reply
;
129 struct i2o_device_identity
*ident
;
130 struct disk_info info
;
131 int lun
= device_get_unit(dev
);
134 if (!(reply
= iop_get_util_params(psc
->iop
, psc
->lct
->local_tid
,
135 I2O_PARAMS_OPERATION_FIELD_GET
,
136 I2O_BSA_DEVICE_INFO_GROUP_NO
)))
139 psc
->info
= kmalloc(sizeof(struct i2o_bsa_device
), M_PSTRAID
, M_INTWAIT
);
140 bcopy(reply
->result
, psc
->info
, sizeof(struct i2o_bsa_device
));
141 contigfree(reply
, PAGE_SIZE
, M_PSTRAID
);
143 if (!(reply
= iop_get_util_params(psc
->iop
, psc
->lct
->local_tid
,
144 I2O_PARAMS_OPERATION_FIELD_GET
,
145 I2O_UTIL_DEVICE_IDENTITY_GROUP_NO
)))
147 ident
= (struct i2o_device_identity
*)reply
->result
;
149 kprintf("pst: vendor=<%.16s> product=<%.16s>\n",
150 ident
->vendor
, ident
->product
);
151 kprintf("pst: description=<%.16s> revision=<%.8s>\n",
152 ident
->description
, ident
->revision
);
153 kprintf("pst: capacity=%lld blocksize=%d\n",
154 psc
->info
->capacity
, psc
->info
->block_size
);
156 bpack(ident
->vendor
, ident
->vendor
, 16);
157 bpack(ident
->product
, ident
->product
, 16);
158 ksprintf(name
, "%s %s", ident
->vendor
, ident
->product
);
159 contigfree(reply
, PAGE_SIZE
, M_PSTRAID
);
161 bioq_init(&psc
->bio_queue
);
163 psc
->device
= disk_create(lun
, &psc
->disk
, &pst_ops
);
164 psc
->device
->si_drv1
= psc
;
165 psc
->device
->si_iosize_max
= 64 * 1024; /*I2O_SGL_MAX_SEGS * PAGE_SIZE;*/
167 bzero(&info
, sizeof(info
));
168 info
.d_media_blksize
= psc
->info
->block_size
; /* mandatory */
169 info
.d_media_size
= psc
->info
->capacity
; /* (in bytes) */
171 info
.d_secpertrack
= 63; /* optional */
173 info
.d_secpercyl
= info
.d_nheads
* info
.d_secpertrack
;
175 (psc
->info
->capacity
/ psc
->info
->block_size
) / info
.d_secpercyl
;
177 disk_setdiskinfo(&psc
->disk
, &info
);
179 devstat_add_entry(&psc
->stats
, "pst", lun
, psc
->info
->block_size
,
180 DEVSTAT_NO_ORDERED_TAGS
,
181 DEVSTAT_TYPE_DIRECT
| DEVSTAT_TYPE_IF_IDE
,
182 DEVSTAT_PRIORITY_DISK
);
184 kprintf("pst%d: %lluMB <%.40s> [%d/%d/%d] on %.16s\n", lun
,
185 info
.d_media_size
/ (1024 * 1024), name
,
186 info
.d_ncylinders
, info
.d_nheads
, info
.d_secpertrack
,
187 device_get_nameunit(psc
->iop
->dev
));
189 EVENTHANDLER_REGISTER(shutdown_post_sync
, pst_shutdown
,
190 dev
, SHUTDOWN_PRI_DRIVER
);
197 pst_shutdown(device_t dev
)
199 struct pst_softc
*psc
= device_get_softc(dev
);
200 struct i2o_bsa_cache_flush_message
*msg
;
203 mfa
= iop_get_mfa(psc
->iop
);
204 msg
= (struct i2o_bsa_cache_flush_message
*)(psc
->iop
->ibase
+ mfa
);
205 bzero(msg
, sizeof(struct i2o_bsa_cache_flush_message
));
206 msg
->version_offset
= 0x01;
207 msg
->message_flags
= 0x0;
208 msg
->message_size
= sizeof(struct i2o_bsa_cache_flush_message
) >> 2;
209 msg
->target_address
= psc
->lct
->local_tid
;
210 msg
->initiator_address
= I2O_TID_HOST
;
211 msg
->function
= I2O_BSA_CACHE_FLUSH
;
212 msg
->control_flags
= 0x0; /* 0x80 = post progress reports */
213 if (iop_queue_wait_msg(psc
->iop
, mfa
, (struct i2o_basic_message
*)msg
))
214 kprintf("pst: shutdown failed!\n");
220 pststrategy(struct dev_strategy_args
*ap
)
222 struct pst_softc
*psc
= ap
->a_head
.a_dev
->si_drv1
;
225 bioqdisksort(&psc
->bio_queue
, ap
->a_bio
);
232 pst_start(struct pst_softc
*psc
)
234 struct pst_request
*request
;
239 if (psc
->outstanding
< (I2O_IOP_OUTBOUND_FRAME_COUNT
- 1) &&
240 (bio
= bioq_first(&psc
->bio_queue
))) {
241 if ((mfa
= iop_get_mfa(psc
->iop
)) != 0xffffffff) {
242 request
= kmalloc(sizeof(struct pst_request
),
243 M_PSTRAID
, M_INTWAIT
| M_ZERO
);
248 callout_init(&request
->timeout
);
250 callout_reset(&request
->timeout
, 10 * hz
, pst_timeout
, request
);
251 bioq_remove(&psc
->bio_queue
, bio
);
253 devstat_start_transaction(&psc
->stats
);
254 if (pst_rw(request
)) {
255 devstat_end_transaction_buf(&psc
->stats
, bp
);
257 bp
->b_flags
|= B_ERROR
;
259 iop_free_mfa(request
->psc
->iop
, request
->mfa
);
261 callout_stop(&request
->timeout
);
262 kfree(request
, M_PSTRAID
);
269 pst_done(struct iop_softc
*sc
, u_int32_t mfa
, struct i2o_single_reply
*reply
)
271 struct pst_request
*request
=
272 (struct pst_request
*)reply
->transaction_context
;
273 struct pst_softc
*psc
= request
->psc
;
274 struct buf
*bp
= request
->bio
->bio_buf
;
276 callout_stop(&request
->timeout
);
277 bp
->b_resid
= bp
->b_bcount
- reply
->donecount
;
278 devstat_end_transaction_buf(&psc
->stats
, bp
);
281 bp
->b_flags
|= B_ERROR
;
283 biodone(request
->bio
);
284 kfree(request
, M_PSTRAID
);
286 psc
->iop
->reg
->oqueue
= mfa
;
293 pst_timeout(void *xrequest
)
295 struct pst_request
*request
= xrequest
;
296 struct buf
*bp
= request
->bio
->bio_buf
;
299 kprintf("pst: timeout mfa=0x%08x cmd=%s\n",
300 request
->mfa
, (bp
->b_cmd
== BUF_CMD_READ
) ? "READ" : "WRITE");
301 iop_free_mfa(request
->psc
->iop
, request
->mfa
);
302 if ((request
->mfa
= iop_get_mfa(request
->psc
->iop
)) == 0xffffffff) {
303 kprintf("pst: timeout no mfa possible\n");
304 devstat_end_transaction_buf(&request
->psc
->stats
, bp
);
306 bp
->b_flags
|= B_ERROR
;
307 biodone(request
->bio
);
308 request
->psc
->outstanding
--;
313 callout_reset(&request
->timeout
, 10 * hz
, pst_timeout
, request
);
314 if (pst_rw(request
)) {
315 iop_free_mfa(request
->psc
->iop
, request
->mfa
);
316 devstat_end_transaction_buf(&request
->psc
->stats
, bp
);
318 bp
->b_flags
|= B_ERROR
;
319 biodone(request
->bio
);
320 request
->psc
->outstanding
--;
326 pst_rw(struct pst_request
*request
)
328 struct i2o_bsa_rw_block_message
*msg
;
330 struct buf
*bp
= request
->bio
->bio_buf
;
332 msg
= (struct i2o_bsa_rw_block_message
*)
333 (request
->psc
->iop
->ibase
+ request
->mfa
);
334 bzero(msg
, sizeof(struct i2o_bsa_rw_block_message
));
335 msg
->version_offset
= 0x81;
336 msg
->message_flags
= 0x0;
337 msg
->message_size
= sizeof(struct i2o_bsa_rw_block_message
) >> 2;
338 msg
->target_address
= request
->psc
->lct
->local_tid
;
339 msg
->initiator_address
= I2O_TID_HOST
;
340 if (bp
->b_cmd
== BUF_CMD_READ
) {
341 msg
->function
= I2O_BSA_BLOCK_READ
;
342 msg
->control_flags
= 0x0; /* 0x0c = read cache + readahead */
343 msg
->fetch_ahead
= 0x0; /* 8 Kb */
347 msg
->function
= I2O_BSA_BLOCK_WRITE
;
348 msg
->control_flags
= 0x0; /* 0x10 = write behind cache */
349 msg
->fetch_ahead
= 0x0;
350 sgl_flag
= I2O_SGL_DIR
;
352 msg
->initiator_context
= (u_int32_t
)pst_done
;
353 msg
->transaction_context
= (u_int32_t
)request
;
354 msg
->time_multiplier
= 1;
355 msg
->bytecount
= bp
->b_bcount
;
356 msg
->lba
= request
->bio
->bio_offset
; /* 64 bits */
357 if (!iop_create_sgl((struct i2o_basic_message
*)msg
, bp
->b_data
,
358 bp
->b_bcount
, sgl_flag
))
360 request
->psc
->iop
->reg
->iqueue
= request
->mfa
;
365 bpack(int8_t *src
, int8_t *dst
, int len
)
368 int8_t *ptr
, *buf
= dst
;
370 for (i
= j
= blank
= 0 ; i
< len
; i
++) {
371 if (blank
&& src
[i
] == ' ') continue;
372 if (blank
&& src
[i
] != ' ') {
386 for (ptr
= buf
; ptr
< buf
+len
; ++ptr
)
389 for (ptr
= buf
+ len
- 1; ptr
>= buf
&& *ptr
== ' '; --ptr
)
393 static device_method_t pst_methods
[] = {
394 DEVMETHOD(device_probe
, pst_probe
),
395 DEVMETHOD(device_attach
, pst_attach
),
399 static driver_t pst_driver
= {
402 sizeof(struct pst_softc
),
405 static devclass_t pst_devclass
;
407 DRIVER_MODULE(pst
, pstpci
, pst_driver
, pst_devclass
, 0, 0);