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-iop.c,v 1.2.2.1 2002/08/18 12:32:36 sos Exp $
29 * $DragonFly: src/sys/dev/raid/pst/pst-iop.c,v 1.2 2003/06/17 04:28:29 dillon Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
38 #include <sys/malloc.h>
41 #include <machine/clock.h>
42 #include <machine/stdarg.h>
43 #include <machine/resource.h>
44 #include <machine/bus.h>
46 #include <pci/pcivar.h>
47 #include <pci/pcireg.h>
49 #include "dev/pst/pst-iop.h"
52 MALLOC_DEFINE(M_PSTIOP, "PSTIOP", "Promise SuperTrak IOP driver");
55 iop_init(struct iop_softc *sc)
57 int mfa, timeout = 10000;
59 while ((mfa = sc->reg->iqueue) == 0xffffffff && --timeout)
62 printf("pstiop: no free mfa\n");
65 iop_free_mfa(sc, mfa);
67 sc->reg->oqueue_intr_mask = 0xffffffff;
70 printf("pstiop: no reset response\n");
74 if (!iop_init_outqueue(sc)) {
75 printf("pstiop: init outbound queue failed\n");
79 /* register iop_attach to be run when interrupts are enabled */
80 if (!(sc->iop_delayed_attach = (struct intr_config_hook *)
81 malloc(sizeof(struct intr_config_hook),
82 M_PSTIOP, M_NOWAIT | M_ZERO))) {
83 printf("pstiop: malloc of delayed attach hook failed\n");
86 sc->iop_delayed_attach->ich_func = (void *)iop_attach;
87 sc->iop_delayed_attach->ich_arg = (void *)sc;
88 if (config_intrhook_establish(sc->iop_delayed_attach)) {
89 printf("pstiop: config_intrhook_establish failed\n");
90 free(sc->iop_delayed_attach, M_PSTIOP);
96 iop_attach(struct iop_softc *sc)
100 if (sc->iop_delayed_attach) {
101 config_intrhook_disestablish(sc->iop_delayed_attach);
102 free(sc->iop_delayed_attach, M_PSTIOP);
103 sc->iop_delayed_attach = NULL;
106 if (!iop_get_lct(sc)) {
107 printf("pstiop: get LCT failed\n");
111 /* figure out what devices are here and config as needed */
112 for (i = 0; sc->lct[i].entry_size == I2O_LCT_ENTRYSIZE; i++) {
114 struct i2o_get_param_reply *reply;
116 printf("pstiop: LCT entry %d ", i);
117 printf("class=%04x ", sc->lct[i].class);
118 printf("sub=%04x ", sc->lct[i].sub_class);
119 printf("localtid=%04x ", sc->lct[i].local_tid);
120 printf("usertid=%04x ", sc->lct[i].user_tid);
121 printf("parentid=%04x\n", sc->lct[i].parent_tid);
123 if ((reply = iop_get_util_params(sc, sc->lct[i].local_tid,
124 I2O_PARAMS_OPERATION_FIELD_GET,
125 I2O_UTIL_DEVICE_IDENTITY_GROUP_NO))) {
126 struct i2o_device_identity *ident =
127 (struct i2o_device_identity *)reply->result;
128 printf("pstiop: vendor=<%.16s> product=<%.16s>\n",
129 ident->vendor, ident->product);
130 printf("pstiop: description=<%.16s> revision=<%.8s>\n",
131 ident->description, ident->revision);
132 contigfree(reply, PAGE_SIZE, M_PSTIOP);
136 if (sc->lct[i].user_tid != I2O_TID_NONE &&
137 sc->lct[i].user_tid != I2O_TID_HOST)
140 switch (sc->lct[i].class) {
141 case I2O_CLASS_RANDOM_BLOCK_STORAGE:
142 pst_add_raid(sc, &sc->lct[i]);
146 /* setup and enable interrupts */
147 bus_setup_intr(sc->dev, sc->r_irq, INTR_TYPE_BIO, iop_intr, sc,&sc->handle);
148 sc->reg->oqueue_intr_mask = 0x0;
154 struct iop_softc *sc = (struct iop_softc *)data;
155 struct i2o_single_reply *reply;
158 /* we might get more than one finished request pr interrupt */
160 if ((mfa = sc->reg->oqueue) == 0xffffffff)
161 if ((mfa = sc->reg->oqueue) == 0xffffffff)
164 reply = (struct i2o_single_reply *)(sc->obase + (mfa - sc->phys_obase));
166 /* if this is a event register reply, shout! */
167 if (reply->function == I2O_UTIL_EVENT_REGISTER) {
168 struct i2o_util_event_reply_message *event =
169 (struct i2o_util_event_reply_message *)reply;
171 printf("pstiop: EVENT!! idx=%08x data=%08x\n",
172 event->event_mask, event->event_data[0]);
176 /* if reply is a failurenotice we need to free the original mfa */
177 if (reply->message_flags & I2O_MESSAGE_FLAGS_FAIL)
178 iop_free_mfa(sc,((struct i2o_fault_reply *)(reply))->preserved_mfa);
180 /* reply->initiator_context points to the service routine */
181 ((void (*)(struct iop_softc *, u_int32_t, struct i2o_single_reply *))
182 (reply->initiator_context))(sc, mfa, reply);
187 iop_reset(struct iop_softc *sc)
189 struct i2o_exec_iop_reset_message *msg;
190 int mfa, timeout = 5000;
191 volatile u_int32_t reply = 0;
193 mfa = iop_get_mfa(sc);
194 msg = (struct i2o_exec_iop_reset_message *)(sc->ibase + mfa);
195 bzero(msg, sizeof(struct i2o_exec_iop_reset_message));
196 msg->version_offset = 0x1;
197 msg->message_flags = 0x0;
198 msg->message_size = sizeof(struct i2o_exec_iop_reset_message) >> 2;
199 msg->target_address = I2O_TID_IOP;
200 msg->initiator_address = I2O_TID_HOST;
201 msg->function = I2O_EXEC_IOP_RESET;
202 msg->status_word_low_addr = vtophys(&reply);
203 msg->status_word_high_addr = 0;
205 sc->reg->iqueue = mfa;
207 while (--timeout && !reply)
210 /* wait for iqueue ready */
212 while ((mfa = sc->reg->iqueue) == 0xffffffff && --timeout)
215 iop_free_mfa(sc, mfa);
220 iop_init_outqueue(struct iop_softc *sc)
222 struct i2o_exec_init_outqueue_message *msg;
223 int i, mfa, timeout = 5000;
224 volatile u_int32_t reply = 0;
226 if (!(sc->obase = contigmalloc(I2O_IOP_OUTBOUND_FRAME_COUNT *
227 I2O_IOP_OUTBOUND_FRAME_SIZE,
229 0x00010000, 0xFFFFFFFF,
230 sizeof(u_int32_t), 0))) {
231 printf("pstiop: contigmalloc of outqueue buffers failed!\n");
234 sc->phys_obase = vtophys(sc->obase);
235 mfa = iop_get_mfa(sc);
236 msg = (struct i2o_exec_init_outqueue_message *)(sc->ibase + mfa);
237 bzero(msg, sizeof(struct i2o_exec_init_outqueue_message));
238 msg->version_offset = 0x61;
239 msg->message_flags = 0x0;
240 msg->message_size = sizeof(struct i2o_exec_init_outqueue_message) >> 2;
241 msg->target_address = I2O_TID_IOP;
242 msg->initiator_address = I2O_TID_HOST;
243 msg->function = I2O_EXEC_OUTBOUND_INIT;
244 msg->host_pagesize = PAGE_SIZE;
245 msg->init_code = 0x00; /* SOS XXX should be 0x80 == OS */
246 msg->queue_framesize = I2O_IOP_OUTBOUND_FRAME_SIZE / sizeof(u_int32_t);
247 msg->sgl[0].flags = I2O_SGL_SIMPLE | I2O_SGL_END | I2O_SGL_EOB;
248 msg->sgl[0].count = sizeof(reply);
249 msg->sgl[0].phys_addr[0] = vtophys(&reply);
250 msg->sgl[1].flags = I2O_SGL_END | I2O_SGL_EOB;
251 msg->sgl[1].count = 1;
252 msg->sgl[1].phys_addr[0] = 0;
254 sc->reg->iqueue = mfa;
256 /* wait for init to complete */
257 while (--timeout && reply != I2O_EXEC_OUTBOUND_INIT_COMPLETE)
261 printf("pstiop: timeout waiting for init-complete response\n");
262 iop_free_mfa(sc, mfa);
266 /* now init our oqueue bufs */
267 for (i = 0; i < I2O_IOP_OUTBOUND_FRAME_COUNT; i++) {
268 sc->reg->oqueue = sc->phys_obase + (i * I2O_IOP_OUTBOUND_FRAME_SIZE);
272 iop_free_mfa(sc, mfa);
277 iop_get_lct(struct iop_softc *sc)
279 struct i2o_exec_get_lct_message *msg;
280 struct i2o_get_lct_reply *reply;
282 #define ALLOCSIZE (PAGE_SIZE + (256 * sizeof(struct i2o_lct_entry)))
284 if (!(reply = contigmalloc(ALLOCSIZE, M_PSTIOP, M_NOWAIT | M_ZERO,
285 0x00010000, 0xFFFFFFFF, sizeof(u_int32_t), 0)))
288 mfa = iop_get_mfa(sc);
289 msg = (struct i2o_exec_get_lct_message *)(sc->ibase + mfa);
290 bzero(msg, sizeof(struct i2o_exec_get_lct_message));
291 msg->version_offset = 0x61;
292 msg->message_flags = 0x0;
293 msg->message_size = sizeof(struct i2o_exec_get_lct_message) >> 2;
294 msg->target_address = I2O_TID_IOP;
295 msg->initiator_address = I2O_TID_HOST;
296 msg->function = I2O_EXEC_LCT_NOTIFY;
297 msg->class = I2O_CLASS_MATCH_ANYCLASS;
298 msg->last_change_id = 0;
300 msg->sgl.flags = I2O_SGL_SIMPLE | I2O_SGL_END | I2O_SGL_EOB;
301 msg->sgl.count = ALLOCSIZE;
302 msg->sgl.phys_addr[0] = vtophys(reply);
304 if (iop_queue_wait_msg(sc, mfa, (struct i2o_basic_message *)msg)) {
305 contigfree(reply, ALLOCSIZE, M_PSTIOP);
308 if (!(sc->lct = malloc(reply->table_size * sizeof(struct i2o_lct_entry),
309 M_PSTIOP, M_NOWAIT | M_ZERO))) {
310 contigfree(reply, ALLOCSIZE, M_PSTIOP);
313 bcopy(&reply->entry[0], sc->lct,
314 reply->table_size * sizeof(struct i2o_lct_entry));
315 sc->lct_count = reply->table_size;
316 contigfree(reply, ALLOCSIZE, M_PSTIOP);
320 struct i2o_get_param_reply *
321 iop_get_util_params(struct iop_softc *sc, int target, int operation, int group)
323 struct i2o_util_get_param_message *msg;
324 struct i2o_get_param_operation *param;
325 struct i2o_get_param_reply *reply;
328 if (!(param = contigmalloc(PAGE_SIZE, M_PSTIOP, M_NOWAIT | M_ZERO,
329 0x00010000, 0xFFFFFFFF, sizeof(u_int32_t), 0)))
332 if (!(reply = contigmalloc(PAGE_SIZE, M_PSTIOP, M_NOWAIT | M_ZERO,
333 0x00010000, 0xFFFFFFFF, sizeof(u_int32_t), 0)))
336 mfa = iop_get_mfa(sc);
337 msg = (struct i2o_util_get_param_message *)(sc->ibase + mfa);
338 bzero(msg, sizeof(struct i2o_util_get_param_message));
339 msg->version_offset = 0x51;
340 msg->message_flags = 0x0;
341 msg->message_size = sizeof(struct i2o_util_get_param_message) >> 2;
342 msg->target_address = target;
343 msg->initiator_address = I2O_TID_HOST;
344 msg->function = I2O_UTIL_PARAMS_GET;
345 msg->operation_flags = 0;
347 param->operation_count = 1;
348 param->operation[0].operation = operation;
349 param->operation[0].group = group;
350 param->operation[0].field_count = 0xffff;
352 msg->sgl[0].flags = I2O_SGL_SIMPLE | I2O_SGL_DIR | I2O_SGL_EOB;
353 msg->sgl[0].count = sizeof(struct i2o_get_param_operation);
354 msg->sgl[0].phys_addr[0] = vtophys(param);
356 msg->sgl[1].flags = I2O_SGL_SIMPLE | I2O_SGL_END | I2O_SGL_EOB;
357 msg->sgl[1].count = PAGE_SIZE;
358 msg->sgl[1].phys_addr[0] = vtophys(reply);
360 if (iop_queue_wait_msg(sc, mfa, (struct i2o_basic_message *)msg) ||
361 reply->error_info_size) {
362 contigfree(reply, PAGE_SIZE, M_PSTIOP);
365 contigfree(param, PAGE_SIZE, M_PSTIOP);
370 iop_get_mfa(struct iop_softc *sc)
375 while ((mfa = sc->reg->iqueue) == 0xffffffff && timeout) {
380 printf("pstiop: no free mfa\n");
385 iop_free_mfa(struct iop_softc *sc, int mfa)
387 struct i2o_basic_message *msg = (struct i2o_basic_message *)(sc->ibase+mfa);
389 bzero(msg, sizeof(struct i2o_basic_message));
391 msg->message_flags = 0x0;
392 msg->message_size = sizeof(struct i2o_basic_message) >> 2;
393 msg->target_address = I2O_TID_IOP;
394 msg->initiator_address = I2O_TID_HOST;
395 msg->function = I2O_UTIL_NOP;
396 sc->reg->iqueue = mfa;
400 iop_queue_wait_msg(struct iop_softc *sc, int mfa, struct i2o_basic_message *msg)
402 struct i2o_single_reply *reply;
403 int out_mfa, status, timeout = 10000;
405 sc->reg->iqueue = mfa;
407 while (--timeout && ((out_mfa = sc->reg->oqueue) == 0xffffffff))
410 printf("pstiop: timeout waiting for message response\n");
411 iop_free_mfa(sc, mfa);
415 reply = (struct i2o_single_reply *)(sc->obase + (out_mfa - sc->phys_obase));
416 status = reply->status;
417 sc->reg->oqueue = out_mfa;
422 iop_create_sgl(struct i2o_basic_message *msg, caddr_t data, int count, int dir)
424 struct i2o_sgl *sgl = (struct i2o_sgl *)((int32_t *)msg + msg->offset);
425 u_int32_t sgl_count, sgl_phys;
428 if (((uintptr_t)data & 3) || (count & 3)) {
429 printf("pstiop: non aligned DMA transfer attempted\n");
433 printf("pstiop: zero length DMA transfer attempted\n");
437 sgl_count = min(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK)));
438 sgl_phys = vtophys(data);
439 sgl->flags = dir | I2O_SGL_PAGELIST | I2O_SGL_EOB | I2O_SGL_END;
445 sgl->phys_addr[i] = sgl_phys;
446 sgl_phys = vtophys(data);
447 data += min(count, PAGE_SIZE);
448 count -= min(count, PAGE_SIZE);
449 if (++i >= I2O_SGL_MAX_SEGS) {
450 printf("pstiop: too many segments in SGL\n");
454 sgl->phys_addr[i] = sgl_phys;
455 msg->message_size += i;