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