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