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