xref: /freebsd/sys/dev/pst/pst-iop.c (revision 7660b554bc59a07be0431c17e0e33815818baa69)
1 /*-
2  * Copyright (c) 2001,2002,2003 S�ren Schmidt <sos@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
16  *
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.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/bus.h>
37 #include <sys/bio.h>
38 #include <sys/malloc.h>
39 #include <sys/lock.h>
40 #include <sys/mutex.h>
41 #include <vm/vm.h>
42 #include <vm/pmap.h>
43 #include <machine/stdarg.h>
44 #include <machine/resource.h>
45 #include <machine/bus.h>
46 #include <sys/rman.h>
47 #include <dev/pci/pcivar.h>
48 #include <dev/pci/pcireg.h>
49 
50 #include "dev/pst/pst-iop.h"
51 
52 struct iop_request {
53     struct i2o_single_reply *reply;
54     u_int32_t mfa;
55 };
56 
57 /* local vars */
58 MALLOC_DEFINE(M_PSTIOP, "PSTIOP", "Promise SuperTrak IOP driver");
59 
60 int
61 iop_init(struct iop_softc *sc)
62 {
63     int mfa, timeout = 10000;
64 
65     while ((mfa = sc->reg->iqueue) == 0xffffffff && --timeout)
66 	DELAY(1000);
67     if (!timeout) {
68 	printf("pstiop: no free mfa\n");
69 	return 0;
70     }
71     iop_free_mfa(sc, mfa);
72 
73     sc->reg->oqueue_intr_mask = 0xffffffff;
74 
75     if (!iop_reset(sc)) {
76 	printf("pstiop: no reset response\n");
77 	return 0;
78     }
79 
80     if (!iop_init_outqueue(sc)) {
81 	printf("pstiop: init outbound queue failed\n");
82 	return 0;
83     }
84 
85     /* register iop_attach to be run when interrupts are enabled */
86     if (!(sc->iop_delayed_attach = (struct intr_config_hook *)
87 				   malloc(sizeof(struct intr_config_hook),
88 				   M_PSTIOP, M_NOWAIT | M_ZERO))) {
89 	printf("pstiop: malloc of delayed attach hook failed\n");
90 	return 0;
91     }
92     sc->iop_delayed_attach->ich_func = (void *)iop_attach;
93     sc->iop_delayed_attach->ich_arg = (void *)sc;
94     if (config_intrhook_establish(sc->iop_delayed_attach)) {
95 	printf("pstiop: config_intrhook_establish failed\n");
96 	free(sc->iop_delayed_attach, M_PSTIOP);
97     }
98     return 1;
99 }
100 
101 void
102 iop_attach(struct iop_softc *sc)
103 {
104     int i;
105 
106     if (sc->iop_delayed_attach) {
107 	config_intrhook_disestablish(sc->iop_delayed_attach);
108 	free(sc->iop_delayed_attach, M_PSTIOP);
109 	sc->iop_delayed_attach = NULL;
110     }
111 
112     if (!iop_get_lct(sc)) {
113 	printf("pstiop: get LCT failed\n");
114 	return;
115     }
116 
117     /* figure out what devices are here and config as needed */
118     for (i = 0; sc->lct[i].entry_size == I2O_LCT_ENTRYSIZE; i++) {
119 #ifdef PSTDEBUG
120 	struct i2o_get_param_reply *reply;
121 
122 	printf("pstiop: LCT entry %d ", i);
123 	printf("class=%04x ", sc->lct[i].class);
124 	printf("sub=%04x ", sc->lct[i].sub_class);
125 	printf("localtid=%04x ", sc->lct[i].local_tid);
126 	printf("usertid=%04x ", sc->lct[i].user_tid);
127 	printf("parentid=%04x\n", sc->lct[i].parent_tid);
128 
129 	if ((reply = iop_get_util_params(sc, sc->lct[i].local_tid,
130 					 I2O_PARAMS_OPERATION_FIELD_GET,
131 					 I2O_UTIL_DEVICE_IDENTITY_GROUP_NO))) {
132 	    struct i2o_device_identity *ident =
133 		(struct i2o_device_identity *)reply->result;
134 	    printf("pstiop: vendor=<%.16s> product=<%.16s>\n",
135 		   ident->vendor, ident->product);
136 	    printf("pstiop: description=<%.16s> revision=<%.8s>\n",
137 		   ident->description, ident->revision);
138 	    contigfree(reply, PAGE_SIZE, M_PSTIOP);
139 	}
140 #endif
141 
142 	if (sc->lct[i].user_tid != I2O_TID_NONE &&
143 	    sc->lct[i].user_tid != I2O_TID_HOST)
144 	    continue;
145 
146 	switch (sc->lct[i].class) {
147 	case I2O_CLASS_DDM:
148 	    if (sc->lct[i].sub_class == I2O_SUBCLASS_ISM)
149 		sc->ism = sc->lct[i].local_tid;
150 	    break;
151 
152 	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
153 	    pst_add_raid(sc, &sc->lct[i]);
154 	    break;
155 	}
156     }
157 
158     /* setup and enable interrupts */
159     bus_setup_intr(sc->dev, sc->r_irq, INTR_TYPE_BIO|INTR_ENTROPY|INTR_MPSAFE,
160 		   iop_intr, sc, &sc->handle);
161     sc->reg->oqueue_intr_mask = 0x0;
162 }
163 
164 void
165 iop_intr(void *data)
166 {
167     struct iop_softc *sc = (struct iop_softc *)data;
168     struct i2o_single_reply *reply;
169     u_int32_t mfa;
170 
171     /* we might get more than one finished request pr interrupt */
172     mtx_lock(&sc->mtx);
173     while (1) {
174 	if ((mfa = sc->reg->oqueue) == 0xffffffff)
175 	    if ((mfa = sc->reg->oqueue) == 0xffffffff)
176 		break;
177 
178 	reply = (struct i2o_single_reply *)(sc->obase + (mfa - sc->phys_obase));
179 
180 	/* if this is an event register reply, shout! */
181 	if (reply->function == I2O_UTIL_EVENT_REGISTER) {
182 	    struct i2o_util_event_reply_message *event =
183 		(struct i2o_util_event_reply_message *)reply;
184 
185 	    printf("pstiop: EVENT!! idx=%08x data=%08x\n",
186 		   event->event_mask, event->event_data[0]);
187 	    break;
188 	}
189 
190 	/* if reply is a failurenotice we need to free the original mfa */
191 	if (reply->message_flags & I2O_MESSAGE_FLAGS_FAIL)
192 	    iop_free_mfa(sc,((struct i2o_fault_reply *)(reply))->preserved_mfa);
193 
194 	/* reply->initiator_context points to the service routine */
195 	((void (*)(struct iop_softc *, u_int32_t, struct i2o_single_reply *))
196 	    (reply->initiator_context))(sc, mfa, reply);
197     }
198     mtx_unlock(&sc->mtx);
199 }
200 
201 int
202 iop_reset(struct iop_softc *sc)
203 {
204     struct i2o_exec_iop_reset_message *msg;
205     int mfa, timeout = 5000;
206     volatile u_int32_t reply = 0;
207 
208     mfa = iop_get_mfa(sc);
209     msg = (struct i2o_exec_iop_reset_message *)(sc->ibase + mfa);
210     bzero(msg, sizeof(struct i2o_exec_iop_reset_message));
211     msg->version_offset = 0x1;
212     msg->message_flags = 0x0;
213     msg->message_size = sizeof(struct i2o_exec_iop_reset_message) >> 2;
214     msg->target_address = I2O_TID_IOP;
215     msg->initiator_address = I2O_TID_HOST;
216     msg->function = I2O_EXEC_IOP_RESET;
217     msg->status_word_low_addr = vtophys(&reply);
218     msg->status_word_high_addr = 0;
219 
220     sc->reg->iqueue = mfa;
221 
222     while (--timeout && !reply)
223 	DELAY(1000);
224 
225     /* wait for iqueue ready */
226     timeout = 10000;
227     while ((mfa = sc->reg->iqueue) == 0xffffffff && --timeout)
228 	DELAY(1000);
229 
230     iop_free_mfa(sc, mfa);
231     return reply;
232 }
233 
234 int
235 iop_init_outqueue(struct iop_softc *sc)
236 {
237     struct i2o_exec_init_outqueue_message *msg;
238     int i, mfa, timeout = 5000;
239     volatile u_int32_t reply = 0;
240 
241     if (!(sc->obase = contigmalloc(I2O_IOP_OUTBOUND_FRAME_COUNT *
242 				   I2O_IOP_OUTBOUND_FRAME_SIZE,
243 				   M_PSTIOP, M_NOWAIT,
244 				   0x00010000, 0xFFFFFFFF,
245 				   PAGE_SIZE, 0))) {
246 	printf("pstiop: contigmalloc of outqueue buffers failed!\n");
247 	return 0;
248     }
249     sc->phys_obase = vtophys(sc->obase);
250     mfa = iop_get_mfa(sc);
251     msg = (struct i2o_exec_init_outqueue_message *)(sc->ibase + mfa);
252     bzero(msg, sizeof(struct i2o_exec_init_outqueue_message));
253     msg->version_offset = 0x61;
254     msg->message_flags = 0x0;
255     msg->message_size = sizeof(struct i2o_exec_init_outqueue_message) >> 2;
256     msg->target_address = I2O_TID_IOP;
257     msg->initiator_address = I2O_TID_HOST;
258     msg->function = I2O_EXEC_OUTBOUND_INIT;
259     msg->host_pagesize = PAGE_SIZE;
260     msg->init_code = 0x00; /* SOS XXX should be 0x80 == OS */
261     msg->queue_framesize = I2O_IOP_OUTBOUND_FRAME_SIZE / sizeof(u_int32_t);
262     msg->sgl[0].flags = I2O_SGL_SIMPLE | I2O_SGL_END | I2O_SGL_EOB;
263     msg->sgl[0].count = sizeof(reply);
264     msg->sgl[0].phys_addr[0] = vtophys(&reply);
265     msg->sgl[1].flags = I2O_SGL_END | I2O_SGL_EOB;
266     msg->sgl[1].count = 1;
267     msg->sgl[1].phys_addr[0] = 0;
268 
269     sc->reg->iqueue = mfa;
270 
271     /* wait for init to complete */
272     while (--timeout && reply != I2O_EXEC_OUTBOUND_INIT_COMPLETE)
273 	DELAY(1000);
274 
275     if (!timeout) {
276 	printf("pstiop: timeout waiting for init-complete response\n");
277 	iop_free_mfa(sc, mfa);
278 	return 0;
279     }
280 
281     /* now init our oqueue bufs */
282     for (i = 0; i < I2O_IOP_OUTBOUND_FRAME_COUNT; i++) {
283 	sc->reg->oqueue = sc->phys_obase + (i * I2O_IOP_OUTBOUND_FRAME_SIZE);
284 	DELAY(1000);
285     }
286 
287     return 1;
288 }
289 
290 int
291 iop_get_lct(struct iop_softc *sc)
292 {
293     struct i2o_exec_get_lct_message *msg;
294     struct i2o_get_lct_reply *reply;
295     int mfa;
296 #define ALLOCSIZE	 (PAGE_SIZE + (256 * sizeof(struct i2o_lct_entry)))
297 
298     if (!(reply = contigmalloc(ALLOCSIZE, M_PSTIOP, M_NOWAIT | M_ZERO,
299 			       0x00010000, 0xFFFFFFFF, PAGE_SIZE, 0)))
300 	return 0;
301 
302     mfa = iop_get_mfa(sc);
303     msg = (struct i2o_exec_get_lct_message *)(sc->ibase + mfa);
304     bzero(msg, sizeof(struct i2o_exec_get_lct_message));
305     msg->version_offset = 0x61;
306     msg->message_flags = 0x0;
307     msg->message_size = sizeof(struct i2o_exec_get_lct_message) >> 2;
308     msg->target_address = I2O_TID_IOP;
309     msg->initiator_address = I2O_TID_HOST;
310     msg->function = I2O_EXEC_LCT_NOTIFY;
311     msg->class = I2O_CLASS_MATCH_ANYCLASS;
312     msg->last_change_id = 0;
313 
314     msg->sgl.flags = I2O_SGL_SIMPLE | I2O_SGL_END | I2O_SGL_EOB;
315     msg->sgl.count = ALLOCSIZE;
316     msg->sgl.phys_addr[0] = vtophys(reply);
317 
318     if (iop_queue_wait_msg(sc, mfa, (struct i2o_basic_message *)msg)) {
319 	contigfree(reply, ALLOCSIZE, M_PSTIOP);
320 	return 0;
321     }
322     if (!(sc->lct = malloc(reply->table_size * sizeof(struct i2o_lct_entry),
323 			   M_PSTIOP, M_NOWAIT | M_ZERO))) {
324 	contigfree(reply, ALLOCSIZE, M_PSTIOP);
325 	return 0;
326     }
327     bcopy(&reply->entry[0], sc->lct,
328 	  reply->table_size * sizeof(struct i2o_lct_entry));
329     sc->lct_count = reply->table_size;
330     contigfree(reply, ALLOCSIZE, M_PSTIOP);
331     return 1;
332 }
333 
334 struct i2o_get_param_reply *
335 iop_get_util_params(struct iop_softc *sc, int target, int operation, int group)
336 {
337     struct i2o_util_get_param_message *msg;
338     struct i2o_get_param_operation *param;
339     struct i2o_get_param_reply *reply;
340     int mfa;
341 
342     if (!(param = contigmalloc(PAGE_SIZE, M_PSTIOP, M_NOWAIT | M_ZERO,
343 			       0x00010000, 0xFFFFFFFF, PAGE_SIZE, 0)))
344 	return NULL;
345 
346     if (!(reply = contigmalloc(PAGE_SIZE, M_PSTIOP, M_NOWAIT | M_ZERO,
347 			       0x00010000, 0xFFFFFFFF, PAGE_SIZE, 0)))
348 	return NULL;
349 
350     mfa = iop_get_mfa(sc);
351     msg = (struct i2o_util_get_param_message *)(sc->ibase + mfa);
352     bzero(msg, sizeof(struct i2o_util_get_param_message));
353     msg->version_offset = 0x51;
354     msg->message_flags = 0x0;
355     msg->message_size = sizeof(struct i2o_util_get_param_message) >> 2;
356     msg->target_address = target;
357     msg->initiator_address = I2O_TID_HOST;
358     msg->function = I2O_UTIL_PARAMS_GET;
359     msg->operation_flags = 0;
360 
361     param->operation_count = 1;
362     param->operation[0].operation = operation;
363     param->operation[0].group = group;
364     param->operation[0].field_count = 0xffff;
365 
366     msg->sgl[0].flags = I2O_SGL_SIMPLE | I2O_SGL_DIR | I2O_SGL_EOB;
367     msg->sgl[0].count = sizeof(struct i2o_get_param_operation);
368     msg->sgl[0].phys_addr[0] = vtophys(param);
369 
370     msg->sgl[1].flags = I2O_SGL_SIMPLE | I2O_SGL_END | I2O_SGL_EOB;
371     msg->sgl[1].count = PAGE_SIZE;
372     msg->sgl[1].phys_addr[0] = vtophys(reply);
373 
374     if (iop_queue_wait_msg(sc, mfa, (struct i2o_basic_message *)msg) ||
375 	reply->error_info_size) {
376 	contigfree(reply, PAGE_SIZE, M_PSTIOP);
377 	reply = NULL;
378     }
379     contigfree(param, PAGE_SIZE, M_PSTIOP);
380     return reply;
381 }
382 
383 u_int32_t
384 iop_get_mfa(struct iop_softc *sc)
385 {
386     u_int32_t mfa;
387     int timeout = 10000;
388 
389     while ((mfa = sc->reg->iqueue) == 0xffffffff && timeout) {
390 	DELAY(1000);
391 	timeout--;
392     }
393     if (!timeout)
394 	printf("pstiop: no free mfa\n");
395     return mfa;
396 }
397 
398 void
399 iop_free_mfa(struct iop_softc *sc, int mfa)
400 {
401     struct i2o_basic_message *msg = (struct i2o_basic_message *)(sc->ibase+mfa);
402 
403     bzero(msg, sizeof(struct i2o_basic_message));
404     msg->version = 0x01;
405     msg->message_flags = 0x0;
406     msg->message_size = sizeof(struct i2o_basic_message) >> 2;
407     msg->target_address = I2O_TID_IOP;
408     msg->initiator_address = I2O_TID_HOST;
409     msg->function = I2O_UTIL_NOP;
410     sc->reg->iqueue = mfa;
411 }
412 
413 static void
414 iop_done(struct iop_softc *sc, u_int32_t mfa, struct i2o_single_reply *reply)
415 {
416     struct iop_request *request =
417         (struct iop_request *)reply->transaction_context;
418 
419     request->reply = reply;
420     request->mfa = mfa;
421     wakeup(request);
422 }
423 
424 int
425 iop_queue_wait_msg(struct iop_softc *sc, int mfa, struct i2o_basic_message *msg)
426 {
427     struct i2o_single_reply *reply;
428     struct iop_request request;
429     u_int32_t out_mfa;
430     int status, timeout = 10000;
431 
432     mtx_lock(&sc->mtx);
433     if (!(sc->reg->oqueue_intr_mask & 0x08)) {
434         msg->transaction_context = (u_int32_t)&request;
435         msg->initiator_context = (u_int32_t)iop_done;
436         sc->reg->iqueue = mfa;
437         if (msleep(&request, &sc->mtx, PRIBIO, "pstwt", 10 * hz)) {
438 	    printf("pstiop: timeout waiting for message response\n");
439 	    iop_free_mfa(sc, mfa);
440 	    mtx_unlock(&sc->mtx);
441 	    return -1;
442 	}
443         status = request.reply->status;
444         sc->reg->oqueue = request.mfa;
445     }
446     else {
447 	sc->reg->iqueue = mfa;
448 	while (--timeout && ((out_mfa = sc->reg->oqueue) == 0xffffffff))
449 	    DELAY(1000);
450 	if (!timeout) {
451 	    printf("pstiop: timeout waiting for message response\n");
452 	    iop_free_mfa(sc, mfa);
453 	    mtx_unlock(&sc->mtx);
454 	    return -1;
455 	}
456 	reply = (struct i2o_single_reply *)(sc->obase+(out_mfa-sc->phys_obase));
457 	status = reply->status;
458 	sc->reg->oqueue = out_mfa;
459     }
460     mtx_unlock(&sc->mtx);
461     return status;
462 }
463 
464 int
465 iop_create_sgl(struct i2o_basic_message *msg, caddr_t data, int count, int dir)
466 {
467     struct i2o_sgl *sgl = (struct i2o_sgl *)((int32_t *)msg + msg->offset);
468     u_int32_t sgl_count, sgl_phys;
469     int i = 0;
470 
471     if (((uintptr_t)data & 3) || (count & 3)) {
472 	printf("pstiop: non aligned DMA transfer attempted\n");
473 	return 0;
474     }
475     if (!count) {
476 	printf("pstiop: zero length DMA transfer attempted\n");
477 	return 0;
478     }
479 
480     sgl_count = min(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK)));
481     sgl_phys = vtophys(data);
482     sgl->flags = dir | I2O_SGL_PAGELIST | I2O_SGL_EOB | I2O_SGL_END;
483     sgl->count = count;
484     data += sgl_count;
485     count -= sgl_count;
486 
487     while (count) {
488 	sgl->phys_addr[i] = sgl_phys;
489 	sgl_phys = vtophys(data);
490 	data += min(count, PAGE_SIZE);
491 	count -= min(count, PAGE_SIZE);
492 	if (++i >= I2O_SGL_MAX_SEGS) {
493 	    printf("pstiop: too many segments in SGL\n");
494 	    return 0;
495 	}
496     }
497     sgl->phys_addr[i] = sgl_phys;
498     msg->message_size += i;
499     return 1;
500 }
501