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