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
54struct iop_request {
55    struct i2o_single_reply *reply;
56    u_int32_t mfa;
57};
58
59/* local vars */
60MALLOC_DEFINE(M_PSTIOP, "PSTIOP", "Promise SuperTrak IOP driver");
61
62int
63iop_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
103void
104iop_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
168void
169iop_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
205int
206iop_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
238int
239iop_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
294int
295iop_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
338struct i2o_get_param_reply *
339iop_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
387u_int32_t
388iop_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
402void
403iop_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
417static void
418iop_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
428int
429iop_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
468int
469iop_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