fwohci.c revision 1.17 1 /* $NetBSD: fwohci.c,v 1.17 2001/03/12 23:22:37 onoe Exp $ */
2
3 /*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * IEEE1394 Open Host Controller Interface
41 * based on OHCI Specification 1.1 (January 6, 2000)
42 * The first version to support network interface part is wrtten by
43 * Atsushi Onoe <onoe (at) netbsd.org>.
44 */
45
46 #include "opt_inet.h"
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/types.h>
51 #include <sys/socket.h>
52 #include <sys/callout.h>
53 #include <sys/device.h>
54 #include <sys/kernel.h>
55 #include <sys/malloc.h>
56 #include <sys/mbuf.h>
57
58 #if __NetBSD_Version__ >= 105010000
59 #include <uvm/uvm_extern.h>
60 #else
61 #include <vm/vm.h>
62 #endif
63
64 #include <machine/bus.h>
65
66 #include <dev/ieee1394/ieee1394reg.h>
67 #include <dev/ieee1394/fwohcireg.h>
68
69 #include <dev/ieee1394/ieee1394var.h>
70 #include <dev/ieee1394/fwohcivar.h>
71
72 static const char * const ieee1394_speeds[] = { IEEE1394_SPD_STRINGS };
73
74 #if 0
75 static int fwohci_dnamem_alloc(struct fwohci_softc *sc, int size, int alignment,
76 bus_dmamap_t *mapp, caddr_t *kvap, int flags);
77 #endif
78 static void fwohci_hw_init(struct fwohci_softc *);
79 static void fwohci_power(int, void *);
80 static void fwohci_shutdown(void *);
81
82 static int fwohci_desc_alloc(struct fwohci_softc *);
83 static struct fwohci_desc *fwohci_desc_get(struct fwohci_softc *, int);
84 static void fwohci_desc_put(struct fwohci_softc *, struct fwohci_desc *, int);
85
86 static int fwohci_ctx_alloc(struct fwohci_softc *, struct fwohci_ctx **,
87 int, int);
88 static void fwohci_ctx_free(struct fwohci_softc *, struct fwohci_ctx *);
89 static void fwohci_ctx_init(struct fwohci_softc *, struct fwohci_ctx *);
90
91 static int fwohci_buf_alloc(struct fwohci_softc *, struct fwohci_buf *);
92 static void fwohci_buf_free(struct fwohci_softc *, struct fwohci_buf *);
93 static void fwohci_buf_init(struct fwohci_softc *);
94 static void fwohci_buf_start(struct fwohci_softc *);
95 static void fwohci_buf_stop(struct fwohci_softc *);
96 static void fwohci_buf_next(struct fwohci_softc *, struct fwohci_ctx *);
97 static int fwohci_buf_pktget(struct fwohci_softc *, struct fwohci_ctx *,
98 caddr_t *, int);
99 static int fwohci_buf_input(struct fwohci_softc *, struct fwohci_ctx *,
100 struct fwohci_pkt *);
101
102 static u_int8_t fwohci_phy_read(struct fwohci_softc *, u_int8_t);
103 static void fwohci_phy_write(struct fwohci_softc *, u_int8_t, u_int8_t);
104 static void fwohci_phy_busreset(struct fwohci_softc *);
105 static void fwohci_phy_input(struct fwohci_softc *, struct fwohci_pkt *);
106
107 static int fwohci_handler_set(struct fwohci_softc *, int, u_int32_t, u_int32_t,
108 int (*)(struct fwohci_softc *, void *, struct fwohci_pkt *),
109 void *);
110
111 static void fwohci_arrq_input(struct fwohci_softc *, struct fwohci_ctx *);
112 static void fwohci_arrs_input(struct fwohci_softc *, struct fwohci_ctx *);
113 static void fwohci_ir_input(struct fwohci_softc *, struct fwohci_ctx *);
114
115 static int fwohci_at_output(struct fwohci_softc *, struct fwohci_ctx *,
116 struct fwohci_pkt *);
117 static void fwohci_at_done(struct fwohci_softc *, struct fwohci_ctx *, int);
118 static void fwohci_atrs_output(struct fwohci_softc *, int, struct fwohci_pkt *,
119 struct fwohci_pkt *);
120
121 static int fwohci_guidrom_init(struct fwohci_softc *);
122 static void fwohci_configrom_init(struct fwohci_softc *);
123
124 static void fwohci_selfid_init(struct fwohci_softc *);
125 static int fwohci_selfid_input(struct fwohci_softc *);
126
127 static void fwohci_csr_init(struct fwohci_softc *);
128 static int fwohci_csr_input(struct fwohci_softc *, void *,
129 struct fwohci_pkt *);
130
131 static void fwohci_uid_collect(struct fwohci_softc *);
132 static int fwohci_uid_input(struct fwohci_softc *, void *,
133 struct fwohci_pkt *);
134 static int fwohci_uid_lookup(struct fwohci_softc *, const u_int8_t *);
135
136 static int fwohci_if_inreg(struct device *, u_int32_t, u_int32_t,
137 void (*)(struct device *, struct mbuf *));
138 static int fwohci_if_input(struct fwohci_softc *, void *, struct fwohci_pkt *);
139 static int fwohci_if_output(struct device *, struct mbuf *,
140 void (*)(struct device *, struct mbuf *));
141
142 #ifdef FW_DEBUG
143 int fw_verbose = 1;
144 int fw_dump = 0;
145 #endif
146
147 int
148 fwohci_init(struct fwohci_softc *sc, const struct evcnt *ev)
149 {
150 int i;
151 u_int32_t val;
152 #if 0
153 int error;
154 #endif
155
156 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ev,
157 sc->sc_sc1394.sc1394_dev.dv_xname, "intr");
158
159 /*
160 * Wait for reset completion
161 */
162 for (i = 0; i < OHCI_LOOP; i++) {
163 val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear);
164 if ((val & OHCI_HCControl_SoftReset) == 0)
165 break;
166 }
167
168 /* What dialect of OHCI is this device?
169 */
170 val = OHCI_CSR_READ(sc, OHCI_REG_Version);
171 printf("%s: OHCI %u.%u", sc->sc_sc1394.sc1394_dev.dv_xname,
172 OHCI_Version_GET_Version(val), OHCI_Version_GET_Revision(val));
173
174 if (fwohci_guidrom_init(sc) != 0) {
175 printf("\n%s: fatal: no global UID ROM\n",
176 sc->sc_sc1394.sc1394_dev.dv_xname);
177 return -1;
178 }
179
180 printf(", %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
181 sc->sc_sc1394.sc1394_guid[0], sc->sc_sc1394.sc1394_guid[1],
182 sc->sc_sc1394.sc1394_guid[2], sc->sc_sc1394.sc1394_guid[3],
183 sc->sc_sc1394.sc1394_guid[4], sc->sc_sc1394.sc1394_guid[5],
184 sc->sc_sc1394.sc1394_guid[6], sc->sc_sc1394.sc1394_guid[7]);
185
186 /* Get the maximum link speed and receive size
187 */
188 val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
189 sc->sc_sc1394.sc1394_link_speed =
190 (val & OHCI_BusOptions_LinkSpd_MASK)
191 >> OHCI_BusOptions_LinkSpd_BITPOS;
192 if (sc->sc_sc1394.sc1394_link_speed < IEEE1394_SPD_MAX) {
193 printf(", %s", ieee1394_speeds[sc->sc_sc1394.sc1394_link_speed]);
194 } else {
195 printf(", unknown speed %u", sc->sc_sc1394.sc1394_link_speed);
196 }
197
198 /* MaxRec is encoded as log2(max_rec_octets)-1
199 */
200 sc->sc_sc1394.sc1394_max_receive =
201 1 << (((val & OHCI_BusOptions_MaxRec_MASK)
202 >> OHCI_BusOptions_MaxRec_BITPOS) + 1);
203 printf(", %u max_rec", sc->sc_sc1394.sc1394_max_receive);
204
205 /*
206 * Count how many isochronous ctx we have.
207 */
208 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskSet, ~0);
209 val = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntMaskClear);
210 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskClear, ~0);
211 for (i = 0; val != 0; val >>= 1) {
212 if (val & 0x1)
213 i++;
214 }
215 sc->sc_isoctx = i;
216 printf(", %d iso_ctx", sc->sc_isoctx);
217
218 printf("\n");
219
220 #if 0
221 error = fwohci_dnamem_alloc(sc, OHCI_CONFIG_SIZE, OHCI_CONFIG_ALIGNMENT,
222 &sc->sc_configrom_map,
223 (caddr_t *) &sc->sc_configrom,
224 BUS_DMA_WAITOK|BUS_DMA_COHERENT);
225 return error;
226 #endif
227
228 /*
229 * Enable Link Power
230 */
231 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS);
232
233 /*
234 * Allocate descriptors
235 */
236 if (fwohci_desc_alloc(sc))
237 return -1;
238
239 /*
240 * Allocate DMA Context
241 */
242 fwohci_ctx_alloc(sc, &sc->sc_ctx_arrq, OHCI_BUF_ARRQ_CNT,
243 OHCI_CTX_ASYNC_RX_REQUEST);
244 fwohci_ctx_alloc(sc, &sc->sc_ctx_arrs, OHCI_BUF_ARRS_CNT,
245 OHCI_CTX_ASYNC_RX_RESPONSE);
246 fwohci_ctx_alloc(sc, &sc->sc_ctx_atrq, 0, OHCI_CTX_ASYNC_TX_REQUEST);
247 fwohci_ctx_alloc(sc, &sc->sc_ctx_atrs, 0, OHCI_CTX_ASYNC_TX_RESPONSE);
248 sc->sc_ctx_ir = malloc(sizeof(sc->sc_ctx_ir[0]) * sc->sc_isoctx,
249 M_DEVBUF, M_WAITOK);
250 for (i = 0; i < sc->sc_isoctx; i++) {
251 sc->sc_ctx_ir[i] = NULL;
252 #if 0
253 fwohci_ctx_alloc(sc, &sc->sc_ctx_ir[i], OHCI_BUF_IR_CNT, i);
254 sc->sc_ctx_ir[i]->fc_isoch = 1;
255 #endif
256 }
257
258 /*
259 * Allocate buffer for configuration ROM and SelfID buffer
260 */
261 fwohci_buf_alloc(sc, &sc->sc_buf_cnfrom);
262 fwohci_buf_alloc(sc, &sc->sc_buf_selfid);
263
264 /*
265 * establish hooks for shutdown and suspend/resume
266 */
267 sc->sc_shutdownhook = shutdownhook_establish(fwohci_shutdown, sc);
268 sc->sc_powerhook = powerhook_establish(fwohci_power, sc);
269 callout_init(&sc->sc_selfid_callout);
270
271 /*
272 * Initialize hardware registers.
273 */
274 fwohci_hw_init(sc);
275
276 /*
277 * Initiate Bus Reset
278 */
279 config_defer(&sc->sc_sc1394.sc1394_dev,
280 (void (*)(struct device *))fwohci_phy_busreset);
281
282 sc->sc_sc1394.sc1394_ifinreg = fwohci_if_inreg;
283 sc->sc_sc1394.sc1394_ifoutput = fwohci_if_output;
284 sc->sc_sc1394.sc1394_if = config_found(&sc->sc_sc1394.sc1394_dev,
285 "fw", fwohci_print);
286
287 return 0;
288 }
289
290 int
291 fwohci_intr(void *arg)
292 {
293 struct fwohci_softc * const sc = arg;
294 int i;
295 int progress = 0;
296 u_int32_t intmask, iso;
297
298 for (;;) {
299 intmask = OHCI_CSR_READ(sc, OHCI_REG_IntEventClear);
300 if (intmask == 0)
301 return progress;
302 OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
303 intmask & ~OHCI_Int_BusReset);
304 #ifdef FW_DEBUG
305 if (fw_verbose > 1) {
306 printf("%s: intmask=0x%08x:",
307 sc->sc_sc1394.sc1394_dev.dv_xname, intmask);
308 if (intmask & OHCI_Int_CycleTooLong)
309 printf(" CycleTooLong");
310 if (intmask & OHCI_Int_UnrecoverableError)
311 printf(" UnrecoverableError");
312 if (intmask & OHCI_Int_CycleInconsistent)
313 printf(" CycleInconsistent");
314 if (intmask & OHCI_Int_BusReset)
315 printf(" BusReset");
316 if (intmask & OHCI_Int_SelfIDComplete)
317 printf(" SelfIDComplete");
318 if (intmask & OHCI_Int_LockRespErr)
319 printf(" LockRespErr");
320 if (intmask & OHCI_Int_PostedWriteErr)
321 printf(" PostedWriteErr");
322 if (intmask & OHCI_Int_ReqTxComplete)
323 printf(" ReqTxComplete(0x%04x)",
324 OHCI_ASYNC_DMA_READ(sc,
325 OHCI_CTX_ASYNC_TX_REQUEST,
326 OHCI_SUBREG_ContextControlClear));
327 if (intmask & OHCI_Int_RespTxComplete)
328 printf(" RespTxComplete(0x%04x)",
329 OHCI_ASYNC_DMA_READ(sc,
330 OHCI_CTX_ASYNC_TX_RESPONSE,
331 OHCI_SUBREG_ContextControlClear));
332 if (intmask & OHCI_Int_ARRS)
333 printf(" ARRS(0x%04x)",
334 OHCI_ASYNC_DMA_READ(sc,
335 OHCI_CTX_ASYNC_RX_RESPONSE,
336 OHCI_SUBREG_ContextControlClear));
337 if (intmask & OHCI_Int_ARRQ)
338 printf(" ARRQ(0x%04x)",
339 OHCI_ASYNC_DMA_READ(sc,
340 OHCI_CTX_ASYNC_RX_REQUEST,
341 OHCI_SUBREG_ContextControlClear));
342 if (intmask & OHCI_Int_IsochRx)
343 printf(" IsochRx(0x%08x)",
344 OHCI_CSR_READ(sc,
345 OHCI_REG_IsoRecvIntEventClear));
346 if (intmask & OHCI_Int_IsochTx)
347 printf(" IsochTx(0x%08x)",
348 OHCI_CSR_READ(sc,
349 OHCI_REG_IsoXmitIntEventClear));
350 if (intmask & OHCI_Int_RQPkt)
351 printf(" RQPkt(0x%04x)",
352 OHCI_ASYNC_DMA_READ(sc,
353 OHCI_CTX_ASYNC_RX_REQUEST,
354 OHCI_SUBREG_ContextControlClear));
355 if (intmask & OHCI_Int_RSPkt)
356 printf(" RSPkt(0x%04x)",
357 OHCI_ASYNC_DMA_READ(sc,
358 OHCI_CTX_ASYNC_RX_RESPONSE,
359 OHCI_SUBREG_ContextControlClear));
360 printf("\n");
361 }
362 #endif /* FW_DEBUG */
363 if (intmask & OHCI_Int_BusReset) {
364 /*
365 * According to OHCI spec 6.1.1 "busReset",
366 * All asynchronous transmit must be stopped before
367 * clearing BusReset. Moreover, the BusReset
368 * interrupt bit should not be cleared during the
369 * SelfID phase. Thus we turned off interrupt mask
370 * bit of BusReset instead until SelfID completion
371 * or SelfID timeout.
372 */
373 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear,
374 OHCI_Int_BusReset);
375 intmask &= OHCI_Int_SelfIDComplete;
376 fwohci_buf_stop(sc);
377 fwohci_buf_init(sc);
378 if (sc->sc_uidtbl != NULL) {
379 free(sc->sc_uidtbl, M_DEVBUF);
380 sc->sc_uidtbl = NULL;
381 }
382 callout_reset(&sc->sc_selfid_callout,
383 OHCI_SELFID_TIMEOUT,
384 (void (*)(void *))fwohci_phy_busreset, sc);
385 sc->sc_nodeid = 0xffff; /* indicate invalid */
386 sc->sc_rootid = 0;
387 sc->sc_irmid = IEEE1394_BCAST_PHY_ID;
388 }
389
390 if (intmask & OHCI_Int_SelfIDComplete) {
391 OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
392 OHCI_Int_BusReset);
393 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet,
394 OHCI_Int_BusReset);
395 callout_stop(&sc->sc_selfid_callout);
396 if (fwohci_selfid_input(sc) == 0) {
397 fwohci_buf_start(sc);
398 fwohci_uid_collect(sc);
399 }
400 }
401
402 if (intmask & OHCI_Int_ReqTxComplete)
403 fwohci_at_done(sc, sc->sc_ctx_atrq, 0);
404 if (intmask & OHCI_Int_RespTxComplete)
405 fwohci_at_done(sc, sc->sc_ctx_atrs, 0);
406 if (intmask & OHCI_Int_RQPkt)
407 fwohci_arrq_input(sc, sc->sc_ctx_arrq);
408 if (intmask & OHCI_Int_RSPkt)
409 fwohci_arrs_input(sc, sc->sc_ctx_arrs);
410
411 if (intmask & OHCI_Int_IsochTx) {
412 iso = OHCI_CSR_READ(sc, OHCI_REG_IsoXmitIntEventClear);
413 OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntEventClear, iso);
414 }
415 if (intmask & OHCI_Int_IsochRx) {
416 iso = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear);
417 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear, iso);
418 for (i = 0; i < sc->sc_isoctx; i++) {
419 if ((iso & (1<<i)) && sc->sc_ctx_ir[i] != NULL)
420 fwohci_ir_input(sc, sc->sc_ctx_ir[i]);
421 }
422 }
423
424 if (!progress) {
425 sc->sc_intrcnt.ev_count++;
426 progress = 1;
427 }
428 }
429 }
430
431 #if 0
432 static int
433 fwohci_dnamem_alloc(struct fwohci_softc *sc, int size, int alignment,
434 bus_dmamap_t *mapp, caddr_t *kvap, int flags)
435 {
436 bus_dma_segment_t segs[1];
437 int error, nsegs, steps;
438
439 steps = 0;
440 error = bus_dmamem_alloc(sc->sc_dmat, size, alignment, alignment,
441 segs, 1, &nsegs, flags);
442 if (error)
443 goto cleanup;
444
445 steps = 1;
446 error = bus_dmamem_map(sc->sc_dmat, segs, nsegs, segs[0].ds_len,
447 kvap, flags);
448 if (error)
449 goto cleanup;
450
451 if (error == 0)
452 error = bus_dmamap_create(sc->sc_dmat, size, 1, alignment,
453 size, flags, mapp);
454 if (error)
455 goto cleanup;
456 if (error == 0)
457 error = bus_dmamap_load(sc->sc_dmat, *mapp, *kvap, size, NULL, flags);
458 if (error)
459 goto cleanup;
460
461 cleanup:
462 switch (steps) {
463 case 1:
464 bus_dmamem_free(sc->sc_dmat, segs, nsegs);
465 }
466
467 return error;
468 }
469 #endif
470
471 int
472 fwohci_print(void *aux, const char *pnp)
473 {
474 char *name = aux;
475
476 if (pnp)
477 printf("%s at %s", name, pnp);
478
479 return UNCONF;
480 }
481
482 static void
483 fwohci_hw_init(struct fwohci_softc *sc)
484 {
485 int i;
486 u_int32_t val;
487
488 /*
489 * Software Reset.
490 */
491 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset);
492 for (i = 0; i < OHCI_LOOP; i++) {
493 val = OHCI_CSR_READ(sc, OHCI_REG_HCControlClear);
494 if ((val & OHCI_HCControl_SoftReset) == 0)
495 break;
496 }
497
498 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS);
499
500 /*
501 * First, initilize CSRs with undefined value to default settings.
502 */
503 val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
504 val |= OHCI_BusOptions_ISC | OHCI_BusOptions_CMC;
505 #if 0
506 val |= OHCI_BusOptions_BMC | OHCI_BusOptions_IRMC;
507 #else
508 val &= ~(OHCI_BusOptions_BMC | OHCI_BusOptions_IRMC);
509 #endif
510 OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val);
511 for (i = 0; i < sc->sc_isoctx; i++) {
512 OHCI_SYNC_RX_DMA_WRITE(sc, i, OHCI_SUBREG_ContextControlClear,
513 ~0);
514 }
515 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear, ~0);
516
517 fwohci_configrom_init(sc);
518 fwohci_selfid_init(sc);
519 fwohci_buf_init(sc);
520 fwohci_csr_init(sc);
521
522 /*
523 * Final CSR settings.
524 */
525 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet,
526 OHCI_LinkControl_CycleTimerEnable |
527 OHCI_LinkControl_RcvSelfID | OHCI_LinkControl_RcvPhyPkt);
528
529 OHCI_CSR_WRITE(sc, OHCI_REG_ATRetries, 0x00000888); /*XXX*/
530
531 /* clear receive filter */
532 OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskHiClear, ~0);
533 OHCI_CSR_WRITE(sc, OHCI_REG_IRMultiChanMaskLoClear, ~0);
534 OHCI_CSR_WRITE(sc, OHCI_REG_AsynchronousRequestFilterHiSet, 0x80000000);
535
536 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear,
537 OHCI_HCControl_NoByteSwapData | OHCI_HCControl_APhyEnhanceEnable);
538
539 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, ~0);
540 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_BusReset |
541 OHCI_Int_SelfIDComplete | OHCI_Int_IsochRx | OHCI_Int_IsochTx |
542 OHCI_Int_RSPkt | OHCI_Int_RQPkt | OHCI_Int_ARRS | OHCI_Int_ARRQ |
543 OHCI_Int_RespTxComplete | OHCI_Int_ReqTxComplete);
544 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_CycleTooLong |
545 OHCI_Int_UnrecoverableError | OHCI_Int_CycleInconsistent |
546 OHCI_Int_LockRespErr | OHCI_Int_PostedWriteErr);
547 OHCI_CSR_WRITE(sc, OHCI_REG_IsoXmitIntMaskSet, ~0);
548 OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntMaskSet, ~0);
549 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_MasterEnable);
550
551 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LinkEnable);
552
553 /*
554 * Start the receivers
555 */
556 fwohci_buf_start(sc);
557 }
558
559 static void
560 fwohci_power(int why, void *arg)
561 {
562 struct fwohci_softc *sc = arg;
563 int s;
564
565 s = splimp();
566 switch (why) {
567 case PWR_SUSPEND:
568 case PWR_STANDBY:
569 fwohci_shutdown(sc);
570 break;
571 case PWR_RESUME:
572 fwohci_hw_init(sc);
573 fwohci_phy_busreset(sc);
574 break;
575 case PWR_SOFTSUSPEND:
576 case PWR_SOFTSTANDBY:
577 case PWR_SOFTRESUME:
578 break;
579 }
580 splx(s);
581 }
582
583 static void
584 fwohci_shutdown(void *arg)
585 {
586 struct fwohci_softc *sc = arg;
587 u_int32_t val;
588
589 callout_stop(&sc->sc_selfid_callout);
590 /* disable all interrupt */
591 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear, OHCI_Int_MasterEnable);
592 fwohci_buf_stop(sc);
593 val = OHCI_CSR_READ(sc, OHCI_REG_BusOptions);
594 val &= ~(OHCI_BusOptions_BMC | OHCI_BusOptions_ISC |
595 OHCI_BusOptions_CMC | OHCI_BusOptions_IRMC);
596 OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val);
597 fwohci_phy_busreset(sc);
598 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LPS);
599 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset);
600 }
601
602 /*
603 * COMMON FUNCTIONS
604 */
605
606 /*
607 * read the PHY Register.
608 */
609 static u_int8_t
610 fwohci_phy_read(struct fwohci_softc *sc, u_int8_t reg)
611 {
612 int i;
613 u_int32_t val;
614
615 OHCI_CSR_WRITE(sc, OHCI_REG_PhyControl,
616 OHCI_PhyControl_RdReg | (reg << OHCI_PhyControl_RegAddr_BITPOS));
617 for (i = 0; i < OHCI_LOOP; i++) {
618 if (OHCI_CSR_READ(sc, OHCI_REG_PhyControl) &
619 OHCI_PhyControl_RdDone)
620 break;
621 }
622 val = OHCI_CSR_READ(sc, OHCI_REG_PhyControl);
623 return (val & OHCI_PhyControl_RdData) >> OHCI_PhyControl_RdData_BITPOS;
624 }
625
626 /*
627 * write the PHY Register.
628 */
629 static void
630 fwohci_phy_write(struct fwohci_softc *sc, u_int8_t reg, u_int8_t val)
631 {
632 int i;
633
634 OHCI_CSR_WRITE(sc, OHCI_REG_PhyControl, OHCI_PhyControl_WrReg |
635 (reg << OHCI_PhyControl_RegAddr_BITPOS) |
636 (val << OHCI_PhyControl_WrData_BITPOS));
637 for (i = 0; i < OHCI_LOOP; i++) {
638 if (!(OHCI_CSR_READ(sc, OHCI_REG_PhyControl) &
639 OHCI_PhyControl_WrReg))
640 break;
641 }
642 }
643
644 /*
645 * Initiate Bus Reset
646 */
647 static void
648 fwohci_phy_busreset(struct fwohci_softc *sc)
649 {
650 int s;
651 u_int8_t val;
652
653 s = splimp();
654 OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
655 OHCI_Int_BusReset | OHCI_Int_SelfIDComplete);
656 OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_BusReset);
657 callout_stop(&sc->sc_selfid_callout);
658 val = fwohci_phy_read(sc, 1);
659 val = (val & 0x80) | /* preserve RHB (force root) */
660 0x40 | /* Initiate Bus Reset */
661 0x3f; /* default GAP count */
662 fwohci_phy_write(sc, 1, val);
663 splx(s);
664 }
665
666 /*
667 * PHY Packet
668 */
669 static void
670 fwohci_phy_input(struct fwohci_softc *sc, struct fwohci_pkt *pkt)
671 {
672 u_int32_t val;
673 u_int8_t key, phyid;
674
675 val = pkt->fp_hdr[1];
676 if (val != ~pkt->fp_hdr[2]) {
677 if (val == 0 && ((*pkt->fp_trail & 0x001f0000) >> 16) ==
678 OHCI_CTXCTL_EVENT_BUS_RESET) {
679 #ifdef FW_DEBUG
680 if (fw_verbose > 1)
681 printf("fwohci_phy_input: BusReset: 0x%08x\n",
682 pkt->fp_hdr[2]);
683 #endif
684 } else {
685 printf("%s: phy packet corrupted (0x%08x, 0x%08x)\n",
686 sc->sc_sc1394.sc1394_dev.dv_xname, val,
687 pkt->fp_hdr[2]);
688 }
689 return;
690 }
691 key = (val & 0xc0000000) >> 30;
692 phyid = (val & 0x3f000000) >> 24;
693 switch (key) {
694 case 0:
695 #ifdef FW_DEBUG
696 if (fw_verbose > 1) {
697 printf("fwohci_phy_input: PHY Config from %d:", phyid);
698 if (val & 0x00800000)
699 printf(" ForceRoot");
700 if (val & 0x00400000)
701 printf(" Gap=%x", (val & 0x003f0000) >> 16);
702 printf("\n");
703 }
704 #endif
705 break;
706 case 1:
707 #ifdef FW_DEBUG
708 if (fw_verbose > 1)
709 printf("fwohci_phy_input: Link-on from %d\n", phyid);
710 #endif
711 break;
712 case 2:
713 #ifdef FW_DEBUG
714 if (fw_verbose > 1) {
715 printf("fwohci_phy_input: SelfID from %d:", phyid);
716 if (val & 0x00800000) {
717 printf(" #%d", (val & 0x00700000) >> 20);
718 } else {
719 if (val & 0x00400000)
720 printf(" LinkActive");
721 printf(" Gap=%x", (val & 0x003f0000) >> 16);
722 printf(" Spd=S%d",
723 100 << ((val & 0x0000c000) >> 14));
724 if (val & 0x00000800)
725 printf(" Cont");
726 if (val & 0x00000002)
727 printf(" InitiateBusReset");
728 }
729 if (val & 0x00000001)
730 printf(" +");
731 printf("\n");
732 }
733 #endif
734 break;
735 default:
736 printf("%s: unknown PHY packet: 0x%08x\n",
737 sc->sc_sc1394.sc1394_dev.dv_xname, val);
738 break;
739 }
740 }
741
742 /*
743 * Descriptor for context DMA.
744 */
745 static int
746 fwohci_desc_alloc(struct fwohci_softc *sc)
747 {
748 int error, mapsize, dsize;
749
750 /*
751 * allocate descriptor buffer
752 */
753
754 sc->sc_descsize = OHCI_BUF_ARRQ_CNT + OHCI_BUF_ARRS_CNT +
755 OHCI_BUF_ATRQ_CNT + OHCI_BUF_ATRS_CNT +
756 OHCI_BUF_IR_CNT * sc->sc_isoctx + 2;
757 dsize = sizeof(struct fwohci_desc) * sc->sc_descsize;
758 mapsize = howmany(sc->sc_descsize, NBBY);
759 sc->sc_descmap = malloc(mapsize, M_DEVBUF, M_WAITOK);
760 memset(sc->sc_descmap, 0, mapsize);
761
762 if ((error = bus_dmamem_alloc(sc->sc_dmat, dsize, PAGE_SIZE, 0,
763 &sc->sc_dseg, 1, &sc->sc_dnseg, 0)) != 0) {
764 printf("%s: unable to allocate descriptor buffer, error = %d\n",
765 sc->sc_sc1394.sc1394_dev.dv_xname, error);
766 goto fail_0;
767 }
768
769 if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg,
770 dsize, (caddr_t *)&sc->sc_desc, BUS_DMA_COHERENT | BUS_DMA_WAITOK))
771 != 0) {
772 printf("%s: unable to map descriptor buffer, error = %d\n",
773 sc->sc_sc1394.sc1394_dev.dv_xname, error);
774 goto fail_1;
775 }
776
777 if ((error = bus_dmamap_create(sc->sc_dmat, dsize, sc->sc_dnseg,
778 dsize, 0, BUS_DMA_WAITOK, &sc->sc_ddmamap)) != 0) {
779 printf("%s: unable to create descriptor buffer DMA map, "
780 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error);
781 goto fail_2;
782 }
783
784 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_ddmamap, sc->sc_desc,
785 dsize, NULL, BUS_DMA_WAITOK)) != 0) {
786 printf("%s: unable to load descriptor buffer DMA map, "
787 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error);
788 goto fail_3;
789 }
790
791 return 0;
792
793 fail_3:
794 bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap);
795 fail_2:
796 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_desc, dsize);
797 fail_1:
798 bus_dmamem_free(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg);
799 fail_0:
800 return error;
801 }
802
803 static struct fwohci_desc *
804 fwohci_desc_get(struct fwohci_softc *sc, int ndesc)
805 {
806 int i, n;
807
808 for (n = 0; n <= sc->sc_descsize - ndesc; n++) {
809 for (i = 0; ; i++) {
810 if (i == ndesc) {
811 for (i = 0; i < ndesc; i++)
812 setbit(sc->sc_descmap, n + i);
813 return sc->sc_desc + n;
814 }
815 if (isset(sc->sc_descmap, n + i))
816 break;
817 }
818 }
819 return NULL;
820 }
821
822 static void
823 fwohci_desc_put(struct fwohci_softc *sc, struct fwohci_desc *fd, int ndesc)
824 {
825 int i, n;
826
827 n = fd - sc->sc_desc;
828 for (i = 0; i < ndesc; i++, n++) {
829 #ifdef DIAGNOSTICS
830 if (isclr(sc->sc_descmap, n))
831 panic("fwohci_desc_put: duplicated free");
832 #endif
833 clrbit(sc->sc_descmap, n);
834 }
835 }
836
837 /*
838 * Asyncronous/Isochronous Transmit/Receive Context
839 */
840 static int
841 fwohci_ctx_alloc(struct fwohci_softc *sc, struct fwohci_ctx **fcp,
842 int bufcnt, int ctx)
843 {
844 int i, error;
845 struct fwohci_ctx *fc;
846 struct fwohci_buf *fb;
847 struct fwohci_desc *fd;
848
849 fc = malloc(sizeof(*fc) + sizeof(*fb) * bufcnt, M_DEVBUF, M_WAITOK);
850 memset(fc, 0, sizeof(*fc) + sizeof(*fb) * bufcnt);
851 LIST_INIT(&fc->fc_handler);
852 TAILQ_INIT(&fc->fc_buf);
853 fc->fc_ctx = ctx;
854 fc->fc_bufcnt = bufcnt;
855 fb = (struct fwohci_buf *)&fc[1];
856 for (i = 0; i < bufcnt; i++, fb++) {
857 if ((error = fwohci_buf_alloc(sc, fb)) != 0)
858 goto fail;
859 if ((fd = fwohci_desc_get(sc, 1)) == NULL) {
860 error = ENOBUFS;
861 goto fail;
862 }
863 fb->fb_desc = fd;
864 fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
865 ((caddr_t)fd - (caddr_t)sc->sc_desc);
866 fd->fd_flags = OHCI_DESC_INPUT | OHCI_DESC_STATUS |
867 OHCI_DESC_INTR_ALWAYS | OHCI_DESC_BRANCH;
868 fd->fd_reqcount = fb->fb_dmamap->dm_segs[0].ds_len;
869 fd->fd_data = fb->fb_dmamap->dm_segs[0].ds_addr;
870 TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
871 }
872 *fcp = fc;
873 return 0;
874
875 fail:
876 while (i-- > 0)
877 fwohci_buf_free(sc, --fb);
878 free(fc, M_DEVBUF);
879 return error;
880 }
881
882 static void
883 fwohci_ctx_free(struct fwohci_softc *sc, struct fwohci_ctx *fc)
884 {
885 struct fwohci_buf *fb;
886 struct fwohci_handler *fh;
887
888 while ((fh = LIST_FIRST(&fc->fc_handler)) != NULL)
889 fwohci_handler_set(sc, fh->fh_tcode, fh->fh_key1, fh->fh_key2,
890 NULL, NULL);
891 while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
892 TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
893 fwohci_buf_free(sc, fb);
894 }
895 free(fc, M_DEVBUF);
896 }
897
898 static void
899 fwohci_ctx_init(struct fwohci_softc *sc, struct fwohci_ctx *fc)
900 {
901 struct fwohci_buf *fb, *nfb;
902 struct fwohci_desc *fd;
903 int n;
904
905 for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL; fb = nfb) {
906 nfb = TAILQ_NEXT(fb, fb_list);
907 fb->fb_off = 0;
908 fd = fb->fb_desc;
909 fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0;
910 fd->fd_rescount = fd->fd_reqcount;
911 }
912
913 n = fc->fc_ctx;
914 fb = TAILQ_FIRST(&fc->fc_buf);
915 if (fc->fc_isoch) {
916 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
917 fb->fb_daddr | 1);
918 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlClear,
919 OHCI_CTXCTL_RX_BUFFER_FILL |
920 OHCI_CTXCTL_RX_CYCLE_MATCH_ENABLE |
921 OHCI_CTXCTL_RX_MULTI_CHAN_MODE |
922 OHCI_CTXCTL_RX_DUAL_BUFFER_MODE);
923 OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlSet,
924 OHCI_CTXCTL_RX_ISOCH_HEADER);
925 } else {
926 OHCI_ASYNC_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
927 fb->fb_daddr | 1);
928 }
929 }
930
931 /*
932 * DMA data buffer
933 */
934 static int
935 fwohci_buf_alloc(struct fwohci_softc *sc, struct fwohci_buf *fb)
936 {
937 int error;
938
939 if ((error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
940 PAGE_SIZE, &fb->fb_seg, 1, &fb->fb_nseg, BUS_DMA_WAITOK)) != 0) {
941 printf("%s: unable to allocate buffer, error = %d\n",
942 sc->sc_sc1394.sc1394_dev.dv_xname, error);
943 goto fail_0;
944 }
945
946 if ((error = bus_dmamem_map(sc->sc_dmat, &fb->fb_seg,
947 fb->fb_nseg, PAGE_SIZE, &fb->fb_buf, BUS_DMA_WAITOK)) != 0) {
948 printf("%s: unable to map buffer, error = %d\n",
949 sc->sc_sc1394.sc1394_dev.dv_xname, error);
950 goto fail_1;
951 }
952
953 if ((error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, fb->fb_nseg,
954 PAGE_SIZE, 0, BUS_DMA_WAITOK, &fb->fb_dmamap)) != 0) {
955 printf("%s: unable to create buffer DMA map, "
956 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname,
957 error);
958 goto fail_2;
959 }
960
961 if ((error = bus_dmamap_load(sc->sc_dmat, fb->fb_dmamap,
962 fb->fb_buf, PAGE_SIZE, NULL, BUS_DMA_WAITOK)) != 0) {
963 printf("%s: unable to load buffer DMA map, "
964 "error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname,
965 error);
966 goto fail_3;
967 }
968
969 return 0;
970
971 bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap);
972 fail_3:
973 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
974 fail_2:
975 bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE);
976 fail_1:
977 bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg);
978 fail_0:
979 return error;
980 }
981
982 static void
983 fwohci_buf_free(struct fwohci_softc *sc, struct fwohci_buf *fb)
984 {
985
986 bus_dmamap_unload(sc->sc_dmat, fb->fb_dmamap);
987 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
988 bus_dmamem_unmap(sc->sc_dmat, fb->fb_buf, PAGE_SIZE);
989 bus_dmamem_free(sc->sc_dmat, &fb->fb_seg, fb->fb_nseg);
990 }
991
992 static void
993 fwohci_buf_init(struct fwohci_softc *sc)
994 {
995 int i;
996
997 /*
998 * Initialize for Asynchronous Transmit Queue.
999 */
1000 fwohci_at_done(sc, sc->sc_ctx_atrq, 1);
1001 fwohci_at_done(sc, sc->sc_ctx_atrs, 1);
1002
1003 /*
1004 * Initialize for Asynchronous Receive Queue.
1005 */
1006 fwohci_ctx_init(sc, sc->sc_ctx_arrq);
1007 fwohci_ctx_init(sc, sc->sc_ctx_arrs);
1008
1009 /*
1010 * Initialize for Isochronous Receive Queue.
1011 */
1012 for (i = 0; i < sc->sc_isoctx; i++) {
1013 if (sc->sc_ctx_ir[i] != NULL)
1014 fwohci_ctx_init(sc, sc->sc_ctx_ir[i]);
1015 }
1016 }
1017
1018 static void
1019 fwohci_buf_start(struct fwohci_softc *sc)
1020 {
1021 int i;
1022
1023 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
1024 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1025 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
1026 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1027 for (i = 0; i < sc->sc_isoctx; i++) {
1028 if (sc->sc_ctx_ir[i] != NULL &&
1029 LIST_FIRST(&sc->sc_ctx_ir[i]->fc_handler) != NULL) {
1030 OHCI_SYNC_RX_DMA_WRITE(sc, i,
1031 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1032 }
1033 }
1034 }
1035
1036 static void
1037 fwohci_buf_stop(struct fwohci_softc *sc)
1038 {
1039 int i, j;
1040
1041 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_REQUEST,
1042 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1043 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
1044 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1045 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_REQUEST,
1046 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1047 OHCI_ASYNC_DMA_WRITE(sc, OHCI_CTX_ASYNC_RX_RESPONSE,
1048 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1049 for (i = 0; i < sc->sc_isoctx; i++) {
1050 OHCI_SYNC_RX_DMA_WRITE(sc, i,
1051 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1052 }
1053
1054 /*
1055 * Make sure the transmitter is stopped.
1056 */
1057 for (j = 0; j < OHCI_LOOP; j++) {
1058 if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_REQUEST,
1059 OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)
1060 continue;
1061 if (OHCI_ASYNC_DMA_READ(sc, OHCI_CTX_ASYNC_TX_RESPONSE,
1062 OHCI_SUBREG_ContextControlClear) & OHCI_CTXCTL_ACTIVE)
1063 continue;
1064 break;
1065 }
1066 }
1067
1068 static void
1069 fwohci_buf_next(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1070 {
1071 struct fwohci_buf *fb, *tfb;
1072
1073 while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
1074 if (fb->fb_off != fb->fb_desc->fd_reqcount ||
1075 fb->fb_desc->fd_rescount != 0)
1076 break;
1077 TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
1078 fb->fb_desc->fd_rescount = fb->fb_desc->fd_reqcount;
1079 fb->fb_off = 0;
1080 fb->fb_desc->fd_branch = 0;
1081 tfb = TAILQ_LAST(&fc->fc_buf, fwohci_buf_s);
1082 tfb->fb_desc->fd_branch = fb->fb_daddr | 1;
1083 TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
1084 }
1085 }
1086
1087 static int
1088 fwohci_buf_pktget(struct fwohci_softc *sc, struct fwohci_ctx *fc, caddr_t *pp,
1089 int len)
1090 {
1091 struct fwohci_buf *fb;
1092 struct fwohci_desc *fd;
1093 int bufend;
1094
1095 fb = TAILQ_FIRST(&fc->fc_buf);
1096 again:
1097 fd = fb->fb_desc;
1098 #ifdef FW_DEBUG
1099 if (fw_verbose > 1)
1100 printf("fwohci_buf_pktget: desc %ld, off %d, req %d, res %d,"
1101 " len %d, avail %d\n",
1102 (long)(fd - sc->sc_desc), fb->fb_off, fd->fd_reqcount,
1103 fd->fd_rescount, len,
1104 fd->fd_reqcount - fd->fd_rescount - fb->fb_off);
1105 #endif
1106 bufend = fd->fd_reqcount - fd->fd_rescount;
1107 if (fb->fb_off >= bufend) {
1108 if (fc->fc_isoch && fb->fb_off > 0) {
1109 fb->fb_off = fd->fd_reqcount;
1110 fd->fd_rescount = 0;
1111 }
1112 if (fd->fd_rescount == 0) {
1113 if ((fb = TAILQ_NEXT(fb, fb_list)) != NULL)
1114 goto again;
1115 }
1116 return 0;
1117 }
1118 if (fb->fb_off + len > bufend)
1119 len = bufend - fb->fb_off;
1120 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, fb->fb_off, len,
1121 BUS_DMASYNC_POSTREAD);
1122 *pp = fb->fb_buf + fb->fb_off;
1123 fb->fb_off += roundup(len, 4);
1124 return len;
1125 }
1126
1127 static int
1128 fwohci_buf_input(struct fwohci_softc *sc, struct fwohci_ctx *fc,
1129 struct fwohci_pkt *pkt)
1130 {
1131 caddr_t p;
1132 int len, count, i;
1133
1134 memset(pkt, 0, sizeof(*pkt));
1135 pkt->fp_uio.uio_iov = pkt->fp_iov;
1136 pkt->fp_uio.uio_rw = UIO_WRITE;
1137 pkt->fp_uio.uio_segflg = UIO_SYSSPACE;
1138
1139 /* get first quadlet */
1140 count = 4;
1141 if (fc->fc_isoch) {
1142 /*
1143 * get trailer first, may be bogus data unless status update
1144 * in descriptor is set.
1145 */
1146 len = fwohci_buf_pktget(sc, fc, (caddr_t *)&pkt->fp_trail,
1147 sizeof(*pkt->fp_trail));
1148 if (len <= 0) {
1149 #ifdef FW_DEBUG
1150 if (fw_verbose > 1)
1151 printf("fwohci_buf_input: no input for is#%d\n",
1152 fc->fc_ctx);
1153 #endif
1154 return 0;
1155 }
1156 *pkt->fp_trail = (*pkt->fp_trail & 0xffff) |
1157 (TAILQ_FIRST(&fc->fc_buf)->fb_desc->fd_status << 16);
1158 }
1159 len = fwohci_buf_pktget(sc, fc, &p, count);
1160 if (len <= 0) {
1161 #ifdef FW_DEBUG
1162 if (fw_verbose > 1)
1163 printf("fwohci_buf_input: no input for %d\n",
1164 fc->fc_ctx);
1165 #endif
1166 return 0;
1167 }
1168 pkt->fp_hdr[0] = *(u_int32_t *)p;
1169 pkt->fp_tcode = (pkt->fp_hdr[0] & 0x000000f0) >> 4;
1170 switch (pkt->fp_tcode) {
1171 case IEEE1394_TCODE_WRITE_REQ_QUAD:
1172 case IEEE1394_TCODE_READ_RESP_QUAD:
1173 pkt->fp_hlen = 12;
1174 pkt->fp_dlen = 4;
1175 break;
1176 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
1177 case IEEE1394_TCODE_READ_RESP_BLOCK:
1178 case IEEE1394_TCODE_LOCK_REQ:
1179 case IEEE1394_TCODE_LOCK_RESP:
1180 pkt->fp_hlen = 16;
1181 break;
1182 case IEEE1394_TCODE_STREAM_DATA:
1183 pkt->fp_hlen = 4;
1184 pkt->fp_dlen = pkt->fp_hdr[0] >> 16;
1185 break;
1186 default:
1187 pkt->fp_hlen = 12;
1188 pkt->fp_dlen = 0;
1189 break;
1190 }
1191
1192 /* get header */
1193 while (count < pkt->fp_hlen) {
1194 len = fwohci_buf_pktget(sc, fc, &p, pkt->fp_hlen - count);
1195 if (len == 0) {
1196 printf("fwohci_buf_input: malformed input 1: %d\n",
1197 pkt->fp_hlen - count);
1198 return 0;
1199 }
1200 memcpy((caddr_t)pkt->fp_hdr + count, p, len);
1201 count += len;
1202 }
1203 if (pkt->fp_hlen == 16)
1204 pkt->fp_dlen = pkt->fp_hdr[3] >> 16;
1205 #ifdef FW_DEBUG
1206 if (fw_verbose > 1)
1207 printf("fwohci_buf_input: tcode=0x%x, hlen=%d, dlen=%d\n",
1208 pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen);
1209 #endif
1210
1211 /* get data */
1212 count = 0;
1213 i = 0;
1214 while (count < pkt->fp_dlen) {
1215 len = fwohci_buf_pktget(sc, fc,
1216 (caddr_t *)&pkt->fp_iov[i].iov_base,
1217 pkt->fp_dlen - count);
1218 if (len == 0) {
1219 printf("fwohci_buf_input: malformed input 2: %d\n",
1220 pkt->fp_hlen - count);
1221 return 0;
1222 }
1223 pkt->fp_iov[i++].iov_len = len;
1224 count += len;
1225 }
1226 pkt->fp_uio.uio_iovcnt = i;
1227 pkt->fp_uio.uio_resid = count;
1228
1229 if (!fc->fc_isoch) {
1230 /* get trailer */
1231 len = fwohci_buf_pktget(sc, fc, (caddr_t *)&pkt->fp_trail,
1232 sizeof(*pkt->fp_trail));
1233 if (len <= 0) {
1234 printf("fwohci_buf_input: malformed input 3: %d\n",
1235 pkt->fp_hlen - count);
1236 return 0;
1237 }
1238 }
1239 return 1;
1240 }
1241
1242 static int
1243 fwohci_handler_set(struct fwohci_softc *sc,
1244 int tcode, u_int32_t key1, u_int32_t key2,
1245 int (*handler)(struct fwohci_softc *, void *, struct fwohci_pkt *),
1246 void *arg)
1247 {
1248 struct fwohci_ctx *fc;
1249 struct fwohci_handler *fh;
1250 int i, j;
1251
1252 if (tcode == IEEE1394_TCODE_STREAM_DATA) {
1253 j = sc->sc_isoctx;
1254 fh = NULL;
1255 for (i = 0; i < sc->sc_isoctx; i++) {
1256 if ((fc = sc->sc_ctx_ir[i]) == NULL) {
1257 if (j == sc->sc_isoctx)
1258 j = i;
1259 continue;
1260 }
1261 fh = LIST_FIRST(&fc->fc_handler);
1262 if (fh == NULL) {
1263 j = i;
1264 break;
1265 }
1266 if (fh->fh_tcode == tcode &&
1267 fh->fh_key1 == key1 && fh->fh_key2 == key2)
1268 break;
1269 fh = NULL;
1270 }
1271 if (fh == NULL) {
1272 if (handler == NULL)
1273 return 0;
1274 if (j == sc->sc_isoctx) {
1275 #ifdef FW_DEBUG
1276 if (fw_verbose)
1277 printf("fwohci_handler_set: "
1278 "no more free context\n");
1279 #endif
1280 return ENOMEM;
1281 }
1282 if ((fc = sc->sc_ctx_ir[j]) == NULL) {
1283 fwohci_ctx_alloc(sc, &fc, OHCI_BUF_IR_CNT, j);
1284 fc->fc_isoch = 1;
1285 sc->sc_ctx_ir[j] = fc;
1286 }
1287 }
1288 } else {
1289 switch (tcode) {
1290 case IEEE1394_TCODE_WRITE_REQ_QUAD:
1291 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
1292 case IEEE1394_TCODE_READ_REQ_QUAD:
1293 case IEEE1394_TCODE_READ_REQ_BLOCK:
1294 case IEEE1394_TCODE_LOCK_REQ:
1295 fc = sc->sc_ctx_arrq;
1296 break;
1297 case IEEE1394_TCODE_WRITE_RESP:
1298 case IEEE1394_TCODE_READ_RESP_QUAD:
1299 case IEEE1394_TCODE_READ_RESP_BLOCK:
1300 case IEEE1394_TCODE_LOCK_RESP:
1301 fc = sc->sc_ctx_arrs;
1302 break;
1303 default:
1304 return EIO;
1305 }
1306 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1307 fh = LIST_NEXT(fh, fh_list)) {
1308 if (fh->fh_tcode == tcode &&
1309 fh->fh_key1 == key1 && fh->fh_key2 == key2)
1310 break;
1311 }
1312 }
1313 if (handler == NULL) {
1314 if (fh != NULL) {
1315 LIST_REMOVE(fh, fh_list);
1316 free(fh, M_DEVBUF);
1317 }
1318 if (tcode == IEEE1394_TCODE_STREAM_DATA) {
1319 sc->sc_ctx_ir[fc->fc_ctx] = NULL;
1320 fwohci_ctx_free(sc, fc);
1321 }
1322 return 0;
1323 }
1324 if (fh == NULL) {
1325 fh = malloc(sizeof(*fh), M_DEVBUF, M_NOWAIT);
1326 if (fh == NULL)
1327 return ENOMEM;
1328 LIST_INSERT_HEAD(&fc->fc_handler, fh, fh_list);
1329 }
1330 fh->fh_tcode = tcode;
1331 fh->fh_key1 = key1;
1332 fh->fh_key2 = key2;
1333 fh->fh_handler = handler;
1334 fh->fh_handarg = arg;
1335 #ifdef FW_DEBUG
1336 if (fw_verbose > 1)
1337 printf("fwohci_handler_set: ctx %d, tcode %x, key 0x%x, 0x%x\n",
1338 fc->fc_ctx, tcode, key1, key2);
1339 #endif
1340
1341 if (tcode == IEEE1394_TCODE_STREAM_DATA) {
1342 fwohci_ctx_init(sc, fc);
1343 #ifdef FW_DEBUG
1344 if (fw_verbose > 1)
1345 printf("fwohci_handler_set: SYNC desc %ld\n",
1346 (long)(TAILQ_FIRST(&fc->fc_buf)->fb_desc -
1347 sc->sc_desc));
1348 #endif
1349 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, OHCI_SUBREG_ContextMatch,
1350 (OHCI_CTXMATCH_TAG0 << key2) | key1);
1351 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx,
1352 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1353 }
1354 return 0;
1355 }
1356
1357 /*
1358 * Asyncronous Receive Requests input frontend.
1359 */
1360 static void
1361 fwohci_arrq_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1362 {
1363 int rcode;
1364 u_int32_t key1, key2;
1365 struct fwohci_handler *fh;
1366 struct fwohci_pkt pkt, res;
1367
1368 while (fwohci_buf_input(sc, fc, &pkt)) {
1369 if (pkt.fp_tcode == OHCI_TCODE_PHY) {
1370 fwohci_phy_input(sc, &pkt);
1371 continue;
1372 }
1373 key1 = pkt.fp_hdr[1] & 0xffff;
1374 key2 = pkt.fp_hdr[2];
1375 memset(&res, 0, sizeof(res));
1376 res.fp_uio.uio_rw = UIO_WRITE;
1377 res.fp_uio.uio_segflg = UIO_SYSSPACE;
1378 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1379 fh = LIST_NEXT(fh, fh_list)) {
1380 if (pkt.fp_tcode == fh->fh_tcode &&
1381 key1 == fh->fh_key1 &&
1382 key2 == fh->fh_key2) {
1383 rcode = (*fh->fh_handler)(sc, fh->fh_handarg,
1384 &pkt);
1385 break;
1386 }
1387 }
1388 if (fh == NULL) {
1389 rcode = IEEE1394_RCODE_ADDRESS_ERROR;
1390 #ifdef FW_DEBUG
1391 if (fw_verbose > 1)
1392 printf("fwohci_arrq_input: no listener:"
1393 " tcode 0x%x, addr=0x%04x %08x\n",
1394 pkt.fp_tcode, key1, key2);
1395 #endif
1396 }
1397 if (((*pkt.fp_trail & 0x001f0000) >> 16) !=
1398 OHCI_CTXCTL_EVENT_ACK_PENDING)
1399 continue;
1400 if (rcode != -1)
1401 fwohci_atrs_output(sc, rcode, &pkt, &res);
1402 }
1403 fwohci_buf_next(sc, fc);
1404 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1405 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
1406 }
1407
1408 /*
1409 * Asynchronous Receive Response input frontend.
1410 */
1411 static void
1412 fwohci_arrs_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1413 {
1414 struct fwohci_pkt pkt;
1415 struct fwohci_handler *fh;
1416 u_int16_t srcid;
1417 int rcode, tlabel;
1418
1419 while (fwohci_buf_input(sc, fc, &pkt)) {
1420 srcid = pkt.fp_hdr[1] >> 16;
1421 rcode = (pkt.fp_hdr[1] & 0x0000f000) >> 12;
1422 tlabel = (pkt.fp_hdr[0] & 0x0000fc00) >> 10;
1423 #ifdef FW_DEBUG
1424 if (fw_verbose > 1)
1425 printf("fwohci_arrs_input: tcode 0x%x, from 0x%04x,"
1426 " tlabel 0x%x, rcode 0x%x, hlen %d, dlen %d\n",
1427 pkt.fp_tcode, srcid, tlabel, rcode, pkt.fp_hlen,
1428 pkt.fp_dlen);
1429 #endif
1430 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1431 fh = LIST_NEXT(fh, fh_list)) {
1432 if (pkt.fp_tcode == fh->fh_tcode &&
1433 (srcid & OHCI_NodeId_NodeNumber) == fh->fh_key1 &&
1434 tlabel == fh->fh_key2) {
1435 (*fh->fh_handler)(sc, fh->fh_handarg, &pkt);
1436 LIST_REMOVE(fh, fh_list);
1437 free(fh, M_DEVBUF);
1438 break;
1439 }
1440 }
1441 #ifdef FW_DEBUG
1442 if (fw_verbose > 1)
1443 if (fh == NULL)
1444 printf("fwohci_arrs_input: no lister\n");
1445 #endif
1446 }
1447 fwohci_buf_next(sc, fc);
1448 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1449 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
1450 }
1451
1452 /*
1453 * Isochronous Receive input frontend.
1454 */
1455 static void
1456 fwohci_ir_input(struct fwohci_softc *sc, struct fwohci_ctx *fc)
1457 {
1458 int rcode, chan, tag;
1459 struct iovec *iov;
1460 struct fwohci_handler *fh;
1461 struct fwohci_pkt pkt;
1462
1463 while (fwohci_buf_input(sc, fc, &pkt)) {
1464 chan = (pkt.fp_hdr[0] & 0x00003f00) >> 8;
1465 tag = (pkt.fp_hdr[0] & 0x0000c000) >> 14;
1466 #ifdef FW_DEBUG
1467 if (fw_verbose > 1)
1468 printf("fwohci_ir_input: hdr 0x%08x, tcode %d,"
1469 " hlen %d, dlen %d\n", pkt.fp_hdr[0],
1470 pkt.fp_tcode, pkt.fp_hlen, pkt.fp_dlen);
1471 #endif
1472 if (tag == IEEE1394_TAG_GASP) {
1473 /*
1474 * The pkt with tag=3 is GASP format.
1475 * Move GASP header to header part.
1476 */
1477 if (pkt.fp_dlen < 8)
1478 continue;
1479 iov = pkt.fp_iov;
1480 /* assuming pkt per buffer mode */
1481 pkt.fp_hdr[1] = ntohl(((u_int32_t *)iov->iov_base)[0]);
1482 pkt.fp_hdr[2] = ntohl(((u_int32_t *)iov->iov_base)[1]);
1483 iov->iov_base = (caddr_t)iov->iov_base + 8;
1484 iov->iov_len -= 8;
1485 pkt.fp_hlen += 8;
1486 pkt.fp_dlen -= 8;
1487 }
1488 for (fh = LIST_FIRST(&fc->fc_handler); fh != NULL;
1489 fh = LIST_NEXT(fh, fh_list)) {
1490 if (pkt.fp_tcode == fh->fh_tcode &&
1491 chan == fh->fh_key1 && tag == fh->fh_key2) {
1492 rcode = (*fh->fh_handler)(sc, fh->fh_handarg,
1493 &pkt);
1494 break;
1495 }
1496 }
1497 #ifdef FW_DEBUG
1498 if (fw_verbose > 1) {
1499 if (fh == NULL)
1500 printf("fwohci_ir_input: no handler\n");
1501 else
1502 printf("fwohci_ir_input: rcode %d\n", rcode);
1503 }
1504 #endif
1505 }
1506 fwohci_buf_next(sc, fc);
1507 OHCI_SYNC_RX_DMA_WRITE(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlSet,
1508 OHCI_CTXCTL_WAKE);
1509 }
1510
1511 /*
1512 * Asynchronous Transmit common routine.
1513 */
1514 static int
1515 fwohci_at_output(struct fwohci_softc *sc, struct fwohci_ctx *fc,
1516 struct fwohci_pkt *pkt)
1517 {
1518 struct fwohci_buf *fb;
1519 struct fwohci_desc *fd;
1520 struct mbuf *m, *m0;
1521 int i, ndesc, error, off, len;
1522 u_int32_t val;
1523
1524 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) > sc->sc_rootid) {
1525 /* We can't send anything during selfid duration */
1526 return EAGAIN;
1527 }
1528 #ifdef FW_DEBUG
1529 if (fw_verbose > 1) {
1530 struct iovec *iov;
1531 printf("fwohci_at_output: tcode 0x%x, hlen %d, dlen %d",
1532 pkt->fp_tcode, pkt->fp_hlen, pkt->fp_dlen);
1533 if (fw_dump) {
1534 for (i = 0; i < pkt->fp_hlen/4; i++)
1535 printf("%s%08x", i?" ":"\n\t", pkt->fp_hdr[i]);
1536 printf("$");
1537 for (ndesc = 0, iov = pkt->fp_iov;
1538 ndesc < pkt->fp_uio.uio_iovcnt; ndesc++, iov++) {
1539 for (i = 0; i < iov->iov_len; i++)
1540 printf("%s%02x",
1541 (i%32)?((i%4)?"":" "):"\n\t",
1542 ((u_int8_t *)iov->iov_base)[i]);
1543 printf("$");
1544 }
1545 }
1546 printf("\n");
1547 }
1548 #endif
1549
1550 if ((m = pkt->fp_m) != NULL) {
1551 for (ndesc = 2; m != NULL; m = m->m_next)
1552 ndesc++;
1553 if (ndesc > OHCI_DESC_MAX) {
1554 m0 = NULL;
1555 ndesc = 2;
1556 for (off = 0; off < pkt->fp_dlen; off += len) {
1557 if (m0 == NULL) {
1558 MGETHDR(m0, M_DONTWAIT, MT_DATA);
1559 if (m0 != NULL)
1560 M_COPY_PKTHDR(m0, pkt->fp_m);
1561 m = m0;
1562 } else {
1563 MGET(m->m_next, M_DONTWAIT, MT_DATA);
1564 m = m->m_next;
1565 }
1566 if (m != NULL)
1567 MCLGET(m, M_DONTWAIT);
1568 if (m == NULL || (m->m_flags & M_EXT) == 0) {
1569 m_freem(m0);
1570 return ENOMEM;
1571 }
1572 len = pkt->fp_dlen - off;
1573 if (len > m->m_ext.ext_size)
1574 len = m->m_ext.ext_size;
1575 m_copydata(pkt->fp_m, off, len,
1576 mtod(m, caddr_t));
1577 m->m_len = len;
1578 ndesc++;
1579 }
1580 m_freem(pkt->fp_m);
1581 pkt->fp_m = m0;
1582 }
1583 } else
1584 ndesc = 2 + pkt->fp_uio.uio_iovcnt;
1585
1586 if (ndesc > OHCI_DESC_MAX)
1587 return ENOBUFS;
1588
1589 if (fc->fc_bufcnt > 50) /*XXX*/
1590 return ENOBUFS;
1591 if ((fb = malloc(sizeof(*fb), M_DEVBUF, M_NOWAIT)) == NULL)
1592 return ENOBUFS;
1593 fb->fb_nseg = ndesc;
1594 fb->fb_desc = fwohci_desc_get(sc, ndesc);
1595 if (fb->fb_desc == NULL) {
1596 free(fb, M_DEVBUF);
1597 return ENOBUFS;
1598 }
1599 fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
1600 ((caddr_t)fb->fb_desc - (caddr_t)sc->sc_desc);
1601 fb->fb_m = pkt->fp_m;
1602 fb->fb_callback = pkt->fp_callback;
1603
1604 if (ndesc > 2) {
1605 if ((error = bus_dmamap_create(sc->sc_dmat, pkt->fp_dlen, ndesc,
1606 PAGE_SIZE, 0, BUS_DMA_NOWAIT, &fb->fb_dmamap)) != 0) {
1607 fwohci_desc_put(sc, fb->fb_desc, ndesc);
1608 free(fb, M_DEVBUF);
1609 return error;
1610 }
1611
1612 if (pkt->fp_m != NULL)
1613 error = bus_dmamap_load_mbuf(sc->sc_dmat, fb->fb_dmamap,
1614 pkt->fp_m, BUS_DMA_NOWAIT);
1615 else
1616 error = bus_dmamap_load_uio(sc->sc_dmat, fb->fb_dmamap,
1617 &pkt->fp_uio, BUS_DMA_NOWAIT);
1618 if (error != 0) {
1619 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
1620 fwohci_desc_put(sc, fb->fb_desc, ndesc);
1621 free(fb, M_DEVBUF);
1622 return error;
1623 }
1624 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, pkt->fp_dlen,
1625 BUS_DMASYNC_PREWRITE);
1626 }
1627
1628 fd = fb->fb_desc;
1629 fd->fd_flags = OHCI_DESC_IMMED;
1630 fd->fd_reqcount = pkt->fp_hlen;
1631 fd->fd_data = 0;
1632 fd->fd_branch = 0;
1633 fd->fd_status = 0;
1634 if (fc->fc_ctx == OHCI_CTX_ASYNC_TX_RESPONSE) {
1635 i = 3; /* XXX: 3 sec */
1636 val = OHCI_CSR_READ(sc, OHCI_REG_IsochronousCycleTimer);
1637 fd->fd_timestamp = ((val >> 12) & 0x1fff) |
1638 ((((val >> 25) + i) & 0x7) << 13);
1639 } else
1640 fd->fd_timestamp = 0;
1641 memcpy(fd + 1, pkt->fp_hdr, pkt->fp_hlen);
1642 for (i = 0; i < ndesc - 2; i++) {
1643 fd = fb->fb_desc + 2 + i;
1644 fd->fd_flags = 0;
1645 fd->fd_reqcount = fb->fb_dmamap->dm_segs[i].ds_len;
1646 fd->fd_data = fb->fb_dmamap->dm_segs[i].ds_addr;
1647 fd->fd_branch = 0;
1648 fd->fd_status = 0;
1649 fd->fd_timestamp = 0;
1650 }
1651 fd->fd_flags |= OHCI_DESC_LAST | OHCI_DESC_BRANCH;
1652 fd->fd_flags |= OHCI_DESC_INTR_ALWAYS;
1653
1654 #ifdef FW_DEBUG
1655 if (fw_verbose > 1) {
1656 printf("fwohci_at_output: desc %ld",
1657 (long)(fb->fb_desc - sc->sc_desc));
1658 for (i = 0; i < ndesc * 4; i++)
1659 printf("%s%08x", i&7?" ":"\n\t",
1660 ((u_int32_t *)fb->fb_desc)[i]);
1661 printf("\n");
1662 }
1663 #endif
1664
1665 val = OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx,
1666 OHCI_SUBREG_ContextControlClear);
1667
1668 if (val & OHCI_CTXCTL_RUN) {
1669 if (fc->fc_branch == NULL) {
1670 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1671 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1672 goto run;
1673 }
1674 *fc->fc_branch = fb->fb_daddr | ndesc;
1675 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1676 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_WAKE);
1677 } else {
1678 run:
1679 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1680 OHCI_SUBREG_CommandPtr, fb->fb_daddr | ndesc);
1681 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1682 OHCI_SUBREG_ContextControlSet, OHCI_CTXCTL_RUN);
1683 }
1684 fc->fc_branch = &fd->fd_branch;
1685
1686 fc->fc_bufcnt++;
1687 TAILQ_INSERT_TAIL(&fc->fc_buf, fb, fb_list);
1688 pkt->fp_m = NULL;
1689 return 0;
1690 }
1691
1692 static void
1693 fwohci_at_done(struct fwohci_softc *sc, struct fwohci_ctx *fc, int force)
1694 {
1695 struct fwohci_buf *fb;
1696 struct fwohci_desc *fd;
1697 int i;
1698
1699 while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
1700 fd = fb->fb_desc;
1701 #ifdef FW_DEBUG
1702 if (fw_verbose > 1) {
1703 printf("fwohci_at_done: %sdesc %ld (%d)",
1704 force ? "force " : "",
1705 (long)(fd - sc->sc_desc), fb->fb_nseg);
1706 for (i = 0; i < fb->fb_nseg * 4; i++)
1707 printf("%s%08x", i&7?" ":"\n ",
1708 ((u_int32_t *)fd)[i]);
1709 printf("\n");
1710 }
1711 #endif
1712 if (fb->fb_nseg > 2)
1713 fd += fb->fb_nseg - 1;
1714 if (!force && !(fd->fd_status & OHCI_CTXCTL_ACTIVE))
1715 break;
1716 TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
1717 if (fc->fc_branch == &fd->fd_branch) {
1718 OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx,
1719 OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN);
1720 fc->fc_branch = NULL;
1721 for (i = 0; i < OHCI_LOOP; i++) {
1722 if (!(OHCI_ASYNC_DMA_READ(sc, fc->fc_ctx,
1723 OHCI_SUBREG_ContextControlClear) &
1724 OHCI_CTXCTL_ACTIVE))
1725 break;
1726 }
1727 }
1728 fwohci_desc_put(sc, fb->fb_desc, fb->fb_nseg);
1729 if (fb->fb_nseg > 2)
1730 bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
1731 fc->fc_bufcnt--;
1732 if (fb->fb_callback != NULL) {
1733 (*fb->fb_callback)(sc->sc_sc1394.sc1394_if, fb->fb_m);
1734 fb->fb_callback = NULL;
1735 } else if (fb->fb_m != NULL)
1736 m_freem(fb->fb_m);
1737 free(fb, M_DEVBUF);
1738 }
1739 }
1740
1741 /*
1742 * Asynchronous Transmit Reponse -- in response of request packet.
1743 */
1744 static void
1745 fwohci_atrs_output(struct fwohci_softc *sc, int rcode, struct fwohci_pkt *req,
1746 struct fwohci_pkt *res)
1747 {
1748
1749 if (((*req->fp_trail & 0x001f0000) >> 16) !=
1750 OHCI_CTXCTL_EVENT_ACK_PENDING)
1751 return;
1752
1753 res->fp_hdr[0] = (req->fp_hdr[0] & 0x0000fc00) | 0x00000100;
1754 res->fp_hdr[1] = (req->fp_hdr[1] & 0xffff0000) | (rcode << 12);
1755 switch (req->fp_tcode) {
1756 case IEEE1394_TCODE_WRITE_REQ_QUAD:
1757 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
1758 res->fp_tcode = IEEE1394_TCODE_WRITE_RESP;
1759 res->fp_hlen = 12;
1760 break;
1761 case IEEE1394_TCODE_READ_REQ_QUAD:
1762 res->fp_tcode = IEEE1394_TCODE_READ_RESP_QUAD;
1763 res->fp_hlen = 16;
1764 res->fp_dlen = 0;
1765 if (res->fp_uio.uio_iovcnt == 1 && res->fp_iov[0].iov_len == 4)
1766 res->fp_hdr[3] =
1767 *(u_int32_t *)res->fp_iov[0].iov_base;
1768 res->fp_uio.uio_iovcnt = 0;
1769 break;
1770 case IEEE1394_TCODE_READ_REQ_BLOCK:
1771 case IEEE1394_TCODE_LOCK_REQ:
1772 if (req->fp_tcode == IEEE1394_TCODE_LOCK_REQ)
1773 res->fp_tcode = IEEE1394_TCODE_LOCK_RESP;
1774 else
1775 res->fp_tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
1776 res->fp_hlen = 16;
1777 res->fp_dlen = res->fp_uio.uio_resid;
1778 res->fp_hdr[3] = res->fp_dlen << 16;
1779 break;
1780 }
1781 res->fp_hdr[0] |= (res->fp_tcode << 4);
1782 fwohci_at_output(sc, sc->sc_ctx_atrs, res);
1783 }
1784
1785 /*
1786 * APPLICATION LAYER SERVICES
1787 */
1788
1789 /*
1790 * Retrieve Global UID from GUID ROM
1791 */
1792 static int
1793 fwohci_guidrom_init(struct fwohci_softc *sc)
1794 {
1795 int i, n, off;
1796 u_int32_t val1, val2;
1797
1798 /* Extract the Global UID
1799 */
1800 val1 = OHCI_CSR_READ(sc, OHCI_REG_GUIDHi);
1801 val2 = OHCI_CSR_READ(sc, OHCI_REG_GUIDLo);
1802
1803 if (val1 != 0 || val2 != 0) {
1804 sc->sc_sc1394.sc1394_guid[0] = (val1 >> 24) & 0xff;
1805 sc->sc_sc1394.sc1394_guid[1] = (val1 >> 16) & 0xff;
1806 sc->sc_sc1394.sc1394_guid[2] = (val1 >> 8) & 0xff;
1807 sc->sc_sc1394.sc1394_guid[3] = (val1 >> 0) & 0xff;
1808 sc->sc_sc1394.sc1394_guid[4] = (val2 >> 24) & 0xff;
1809 sc->sc_sc1394.sc1394_guid[5] = (val2 >> 16) & 0xff;
1810 sc->sc_sc1394.sc1394_guid[6] = (val2 >> 8) & 0xff;
1811 sc->sc_sc1394.sc1394_guid[7] = (val2 >> 0) & 0xff;
1812 } else {
1813 val1 = OHCI_CSR_READ(sc, OHCI_REG_Version);
1814 if ((val1 & OHCI_Version_GUID_ROM) == 0)
1815 return -1;
1816 OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom, OHCI_Guid_AddrReset);
1817 for (i = 0; i < OHCI_LOOP; i++) {
1818 val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
1819 if (!(val1 & OHCI_Guid_AddrReset))
1820 break;
1821 }
1822 off = ((val1 & OHCI_Guid_MiniROM_MASK)
1823 >> OHCI_Guid_MiniROM_BITPOS) + 4;
1824 val2 = 0;
1825 for (n = 0; n < off + sizeof(sc->sc_sc1394.sc1394_guid); n++) {
1826 OHCI_CSR_WRITE(sc, OHCI_REG_Guid_Rom,
1827 OHCI_Guid_RdStart);
1828 for (i = 0; i < OHCI_LOOP; i++) {
1829 val1 = OHCI_CSR_READ(sc, OHCI_REG_Guid_Rom);
1830 if (!(val1 & OHCI_Guid_RdStart))
1831 break;
1832 }
1833 if (n < off)
1834 continue;
1835 val1 = (val1 & OHCI_Guid_RdData_MASK)
1836 >> OHCI_Guid_RdData_BITPOS;
1837 sc->sc_sc1394.sc1394_guid[n - off] = val1;
1838 val2 |= val1;
1839 }
1840 if (val2 == 0)
1841 return -1;
1842 }
1843 return 0;
1844 }
1845
1846 /*
1847 * Initialization for Configuration ROM (no DMA context)
1848 */
1849
1850 #define CFR_MAXUNIT 20
1851
1852 struct configromctx {
1853 u_int32_t *ptr;
1854 int curunit;
1855 struct {
1856 u_int32_t *start;
1857 int length;
1858 u_int32_t *refer;
1859 int refunit;
1860 } unit[CFR_MAXUNIT];
1861 };
1862
1863 #define CFR_PUT_DATA4(cfr, d1, d2, d3, d4) \
1864 (*(cfr)->ptr++ = (((d1)<<24) | ((d2)<<16) | ((d3)<<8) | (d4)))
1865
1866 #define CFR_PUT_DATA1(cfr, d) (*(cfr)->ptr++ = (d))
1867
1868 #define CFR_PUT_VALUE(cfr, key, d) (*(cfr)->ptr++ = ((key)<<24) | (d))
1869
1870 #define CFR_PUT_CRC(cfr, n) \
1871 (*(cfr)->unit[n].start = ((cfr)->unit[n].length << 16) | \
1872 fwohci_crc16((cfr)->unit[n].start + 1, (cfr)->unit[n].length))
1873
1874 #define CFR_START_UNIT(cfr, n) \
1875 do { \
1876 if ((cfr)->unit[n].refer != NULL) { \
1877 *(cfr)->unit[n].refer |= \
1878 (cfr)->ptr - (cfr)->unit[n].refer; \
1879 CFR_PUT_CRC(cfr, (cfr)->unit[n].refunit); \
1880 } \
1881 (cfr)->curunit = (n); \
1882 (cfr)->unit[n].start = (cfr)->ptr++; \
1883 } while (0 /* CONSTCOND */)
1884
1885 #define CFR_PUT_REFER(cfr, key, n) \
1886 do { \
1887 (cfr)->unit[n].refer = (cfr)->ptr; \
1888 (cfr)->unit[n].refunit = (cfr)->curunit; \
1889 *(cfr)->ptr++ = (key) << 24; \
1890 } while (0 /* CONSTCOND */)
1891
1892 #define CFR_END_UNIT(cfr) \
1893 do { \
1894 (cfr)->unit[(cfr)->curunit].length = (cfr)->ptr - \
1895 ((cfr)->unit[(cfr)->curunit].start + 1); \
1896 CFR_PUT_CRC(cfr, (cfr)->curunit); \
1897 } while (0 /* CONSTCOND */)
1898
1899 static u_int16_t
1900 fwohci_crc16(u_int32_t *ptr, int len)
1901 {
1902 int shift;
1903 u_int32_t crc, sum, data;
1904
1905 crc = 0;
1906 while (len-- > 0) {
1907 data = *ptr++;
1908 for (shift = 28; shift >= 0; shift -= 4) {
1909 sum = ((crc >> 12) ^ (data >> shift)) & 0x000f;
1910 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum;
1911 }
1912 crc &= 0xffff;
1913 }
1914 return crc;
1915 }
1916
1917 static void
1918 fwohci_configrom_init(struct fwohci_softc *sc)
1919 {
1920 int i;
1921 struct fwohci_buf *fb;
1922 u_int32_t *hdr;
1923 struct configromctx cfr;
1924
1925 fb = &sc->sc_buf_cnfrom;
1926 memset(&cfr, 0, sizeof(cfr));
1927 cfr.ptr = hdr = (u_int32_t *)fb->fb_buf;
1928
1929 /* headers */
1930 CFR_START_UNIT(&cfr, 0);
1931 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusId));
1932 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_BusOptions));
1933 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDHi));
1934 CFR_PUT_DATA1(&cfr, OHCI_CSR_READ(sc, OHCI_REG_GUIDLo));
1935 CFR_END_UNIT(&cfr);
1936 /* copy info_length from crc_length */
1937 *hdr |= (*hdr & 0x00ff0000) << 8;
1938 OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMhdr, *hdr);
1939
1940 /* root directory */
1941 CFR_START_UNIT(&cfr, 1);
1942 CFR_PUT_VALUE(&cfr, 0x03, 0x00005e); /* vendor id */
1943 CFR_PUT_REFER(&cfr, 0x81, 2); /* textual descriptor offset */
1944 CFR_PUT_VALUE(&cfr, 0x0c, 0x0083c0); /* node capability */
1945 /* spt,64,fix,lst,drq */
1946 #ifdef INET
1947 CFR_PUT_REFER(&cfr, 0xd1, 3); /* IPv4 unit directory */
1948 #endif /* INET */
1949 #ifdef INET6
1950 CFR_PUT_REFER(&cfr, 0xd1, 4); /* IPv6 unit directory */
1951 #endif /* INET6 */
1952 CFR_END_UNIT(&cfr);
1953
1954 CFR_START_UNIT(&cfr, 2);
1955 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
1956 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */
1957 CFR_PUT_DATA4(&cfr, 'N', 'e', 't', 'B');
1958 CFR_PUT_DATA4(&cfr, 'S', 'D', 0x00, 0x00);
1959 CFR_END_UNIT(&cfr);
1960
1961 #ifdef INET
1962 /* IPv4 unit directory */
1963 CFR_START_UNIT(&cfr, 3);
1964 CFR_PUT_VALUE(&cfr, 0x12, 0x00005e); /* unit spec id */
1965 CFR_PUT_REFER(&cfr, 0x81, 6); /* textual descriptor offset */
1966 CFR_PUT_VALUE(&cfr, 0x13, 0x000001); /* unit sw version */
1967 CFR_PUT_REFER(&cfr, 0x81, 7); /* textual descriptor offset */
1968 CFR_END_UNIT(&cfr);
1969
1970 CFR_START_UNIT(&cfr, 6);
1971 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
1972 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */
1973 CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A');
1974 CFR_END_UNIT(&cfr);
1975
1976 CFR_START_UNIT(&cfr, 7);
1977 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
1978 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */
1979 CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '4');
1980 CFR_END_UNIT(&cfr);
1981 #endif /* INET */
1982
1983 #ifdef INET6
1984 /* IPv6 unit directory */
1985 CFR_START_UNIT(&cfr, 4);
1986 CFR_PUT_VALUE(&cfr, 0x12, 0x00005e); /* unit spec id */
1987 CFR_PUT_REFER(&cfr, 0x81, 8); /* textual descriptor offset */
1988 CFR_PUT_VALUE(&cfr, 0x13, 0x000002); /* unit sw version */
1989 /* XXX: TBA by IANA */
1990 CFR_PUT_REFER(&cfr, 0x81, 9); /* textual descriptor offset */
1991 CFR_END_UNIT(&cfr);
1992
1993 CFR_START_UNIT(&cfr, 8);
1994 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
1995 CFR_PUT_DATA1(&cfr, 0); /* minimal ASCII */
1996 CFR_PUT_DATA4(&cfr, 'I', 'A', 'N', 'A');
1997 CFR_END_UNIT(&cfr);
1998
1999 CFR_START_UNIT(&cfr, 9);
2000 CFR_PUT_VALUE(&cfr, 0, 0); /* textual descriptor */
2001 CFR_PUT_DATA1(&cfr, 0);
2002 CFR_PUT_DATA4(&cfr, 'I', 'P', 'v', '6');
2003 CFR_END_UNIT(&cfr);
2004 #endif /* INET6 */
2005
2006 #ifdef FW_DEBUG
2007 if (fw_dump) {
2008 printf("%s: Config ROM:", sc->sc_sc1394.sc1394_dev.dv_xname);
2009 for (i = 0; i < cfr.ptr - hdr; i++)
2010 printf("%s%08x", i&7?" ":"\n ", hdr[i]);
2011 printf("\n");
2012 }
2013 #endif /* FW_DEBUG */
2014
2015 /*
2016 * Make network byte order for DMA
2017 */
2018 for (i = 0; i < cfr.ptr - hdr; i++)
2019 HTONL(hdr[i]);
2020 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0,
2021 (caddr_t)cfr.ptr - fb->fb_buf, BUS_DMASYNC_PREWRITE);
2022
2023 OHCI_CSR_WRITE(sc, OHCI_REG_ConfigROMmap,
2024 fb->fb_dmamap->dm_segs[0].ds_addr);
2025 OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_BIBImageValid);
2026 }
2027
2028 /*
2029 * SelfID buffer (no DMA context)
2030 */
2031 static void
2032 fwohci_selfid_init(struct fwohci_softc *sc)
2033 {
2034 struct fwohci_buf *fb;
2035 u_int32_t val;
2036
2037 fb = &sc->sc_buf_selfid;
2038 #ifdef DIAGNOSTICS
2039 if ((fb->fb_dmamap->dm_segs[0].ds_addr & 0x7ff) != 0)
2040 panic("fwohci_selfid_init: not aligned: %p (%ld) %p",
2041 (caddr_t)fb->fb_dmamap->dm_segs[0].ds_addr,
2042 fb->fb_dmamap->dm_segs[0].ds_len, fb->fb_buf);
2043 #endif
2044 memset(fb->fb_buf, 0, fb->fb_dmamap->dm_segs[0].ds_len);
2045 bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0,
2046 fb->fb_dmamap->dm_segs[0].ds_len, BUS_DMASYNC_PREREAD);
2047
2048 OHCI_CSR_WRITE(sc, OHCI_REG_SelfIDBuffer,
2049 fb->fb_dmamap->dm_segs[0].ds_addr);
2050
2051 val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount);
2052 }
2053
2054 static int
2055 fwohci_selfid_input(struct fwohci_softc *sc)
2056 {
2057 int i;
2058 u_int32_t count, val, gen;
2059 u_int32_t *buf;
2060
2061 val = OHCI_CSR_READ(sc, OHCI_REG_SelfIDCount);
2062 if (val & OHCI_SelfID_Error) {
2063 printf("%s: SelfID Error\n", sc->sc_sc1394.sc1394_dev.dv_xname);
2064 return -1;
2065 }
2066 count = (val & OHCI_SelfID_Size_MASK) >> OHCI_SelfID_Size_BITPOS;
2067 gen = (val & OHCI_SelfID_Gen_MASK) >> OHCI_SelfID_Gen_BITPOS;
2068
2069 bus_dmamap_sync(sc->sc_dmat, sc->sc_buf_selfid.fb_dmamap,
2070 0, count << 2, BUS_DMASYNC_POSTREAD);
2071
2072 buf = (u_int32_t *)sc->sc_buf_selfid.fb_buf;
2073 if ((val & OHCI_SelfID_Gen_MASK) != (buf[0] & OHCI_SelfID_Gen_MASK)) {
2074 printf("%s: SelfID Gen mismatch (%d, %d)\n",
2075 sc->sc_sc1394.sc1394_dev.dv_xname, gen,
2076 (buf[0] & OHCI_SelfID_Gen_MASK) >> OHCI_SelfID_Gen_BITPOS);
2077 return -1;
2078 }
2079
2080 #ifdef FW_DEBUG
2081 if (fw_verbose > 1) {
2082 printf("%s: SelfID: 0x%08x", sc->sc_sc1394.sc1394_dev.dv_xname,
2083 val);
2084 for (i = 0; i < count; i++)
2085 printf("%s%08x", i&7?" ":"\n ", buf[i]);
2086 printf("\n");
2087 }
2088 #endif /* FW_DEBUG */
2089
2090 val = OHCI_CSR_READ(sc, OHCI_REG_NodeId);
2091 if ((val & OHCI_NodeId_IDValid) == 0) {
2092 sc->sc_nodeid = 0xffff; /* invalid */
2093 printf("%s: nodeid is invalid\n",
2094 sc->sc_sc1394.sc1394_dev.dv_xname);
2095 return -1;
2096 }
2097 sc->sc_nodeid = val & 0xffff;
2098
2099 for (i = 1; i < count; i += 2) {
2100 if (buf[i] != ~buf[i + 1]) {
2101 printf("%s: SelfID corrupted (%d, 0x%08x, 0x%08x)\n",
2102 sc->sc_sc1394.sc1394_dev.dv_xname, i,
2103 buf[i], buf[i + 1]);
2104 if (i == 1 && buf[i] == 0 && buf[i + 1] == 0) {
2105 /*
2106 * XXX: CXD3222 sometimes fails to DMA
2107 * selfid packet??
2108 */
2109 sc->sc_rootid = (count - 1) / 2 - 1;
2110 sc->sc_irmid = sc->sc_rootid;
2111 break;
2112 }
2113 return -1;
2114 }
2115 if (buf[i] & 0x00000001)
2116 continue; /* more pkt */
2117 if (buf[i] & 0x00800000)
2118 continue; /* external id */
2119 sc->sc_rootid = (buf[i] & 0x3f000000) >> 24;
2120 if ((buf[i] & 0x00400800) == 0x00400800)
2121 sc->sc_irmid = sc->sc_rootid;
2122 }
2123 #ifdef FW_DEBUG
2124 if (fw_verbose)
2125 printf("%s: nodeid=0x%04x(%d), rootid=%d, irmid=%d\n",
2126 sc->sc_sc1394.sc1394_dev.dv_xname,
2127 sc->sc_nodeid, sc->sc_nodeid & OHCI_NodeId_NodeNumber,
2128 sc->sc_rootid, sc->sc_irmid);
2129 #endif
2130
2131 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) > sc->sc_rootid)
2132 return -1;
2133
2134 if ((sc->sc_nodeid & OHCI_NodeId_NodeNumber) == sc->sc_rootid)
2135 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlSet,
2136 OHCI_LinkControl_CycleMaster);
2137 else
2138 OHCI_CSR_WRITE(sc, OHCI_REG_LinkControlClear,
2139 OHCI_LinkControl_CycleMaster);
2140 return 0;
2141 }
2142
2143 /*
2144 * some CSRs are handled by driver.
2145 */
2146 static void
2147 fwohci_csr_init(struct fwohci_softc *sc)
2148 {
2149 int i;
2150 static u_int32_t csr[] = {
2151 CSR_STATE_CLEAR, CSR_STATE_SET, CSR_SB_CYCLE_TIME,
2152 CSR_SB_BUS_TIME, CSR_SB_BUSY_TIMEOUT, CSR_SB_BUS_MANAGER_ID,
2153 CSR_SB_CHANNEL_AVAILABLE_HI, CSR_SB_CHANNEL_AVAILABLE_LO,
2154 CSR_SB_BROADCAST_CHANNEL
2155 };
2156
2157 for (i = 0; i < sizeof(csr) / sizeof(csr[0]); i++) {
2158 fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_QUAD,
2159 CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL);
2160 fwohci_handler_set(sc, IEEE1394_TCODE_READ_REQ_QUAD,
2161 CSR_BASE_HI, CSR_BASE_LO + csr[i], fwohci_csr_input, NULL);
2162 }
2163 sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] = 31; /*XXX*/
2164 }
2165
2166 static int
2167 fwohci_csr_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
2168 {
2169 struct fwohci_pkt res;
2170 u_int32_t reg;
2171
2172 /*
2173 * XXX need to do special functionality other than just r/w...
2174 */
2175 reg = pkt->fp_hdr[2] - CSR_BASE_LO;
2176
2177 if ((reg & 0x03) != 0) {
2178 /* alignment error */
2179 return IEEE1394_RCODE_ADDRESS_ERROR;
2180 }
2181 #ifdef FW_DEBUG
2182 if (fw_verbose > 1)
2183 printf("fwohci_csr_input: CSR[0x%04x]: 0x%08x",
2184 reg, *(u_int32_t *)(&sc->sc_csr[reg]));
2185 #endif
2186 if (pkt->fp_tcode == IEEE1394_TCODE_WRITE_REQ_QUAD) {
2187 #ifdef FW_DEBUG
2188 if (fw_verbose > 1)
2189 printf(" -> 0x%08x\n",
2190 ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base));
2191 #endif
2192 *(u_int32_t *)&sc->sc_csr[reg] =
2193 ntohl(*(u_int32_t *)pkt->fp_iov[0].iov_base);
2194 } else {
2195 #ifdef FW_DEBUG
2196 if (fw_verbose > 1)
2197 printf("\n");
2198 #endif
2199 res.fp_hdr[3] = htonl(*(u_int32_t *)&sc->sc_csr[reg]);
2200 res.fp_iov[0].iov_base = &res.fp_hdr[3];
2201 res.fp_iov[0].iov_len = 4;
2202 res.fp_uio.uio_resid = 4;
2203 res.fp_uio.uio_iovcnt = 1;
2204 fwohci_atrs_output(sc, IEEE1394_RCODE_COMPLETE, pkt, &res);
2205 return -1;
2206 }
2207 return IEEE1394_RCODE_COMPLETE;
2208 }
2209
2210 /*
2211 * Mapping between nodeid and unique ID (EUI-64).
2212 */
2213 static void
2214 fwohci_uid_collect(struct fwohci_softc *sc)
2215 {
2216 int i;
2217 struct fwohci_uidtbl *fu;
2218 struct fwohci_pkt pkt;
2219
2220 if (sc->sc_uidtbl != NULL)
2221 free(sc->sc_uidtbl, M_DEVBUF);
2222 sc->sc_uidtbl = malloc(sizeof(*fu) * (sc->sc_rootid + 1),
2223 M_DEVBUF, M_NOWAIT);
2224 if (sc->sc_uidtbl == NULL)
2225 return;
2226 memset(sc->sc_uidtbl, 0, sizeof(*fu) * (sc->sc_rootid + 1));
2227
2228 memset(&pkt, 0, sizeof(pkt));
2229 for (i = 0, fu = sc->sc_uidtbl; i <= sc->sc_rootid; i++, fu++) {
2230 if (i == (sc->sc_nodeid & OHCI_NodeId_NodeNumber)) {
2231 memcpy(fu->fu_uid, sc->sc_sc1394.sc1394_guid, 8);
2232 fu->fu_valid = 3;
2233 continue;
2234 }
2235 fu->fu_valid = 0;
2236 pkt.fp_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
2237 pkt.fp_hlen = 12;
2238 pkt.fp_dlen = 0;
2239 pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
2240 (pkt.fp_tcode << 4);
2241 pkt.fp_hdr[1] = ((0xffc0 | i) << 16) | CSR_BASE_HI;
2242 pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 12;
2243 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, i,
2244 sc->sc_tlabel, fwohci_uid_input, (void *)0);
2245 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
2246 fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
2247
2248 pkt.fp_hdr[0] = 0x00000100 | (sc->sc_tlabel << 10) |
2249 (pkt.fp_tcode << 4);
2250 pkt.fp_hdr[2] = CSR_BASE_LO + CSR_CONFIG_ROM + 16;
2251 fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, i,
2252 sc->sc_tlabel, fwohci_uid_input, (void *)1);
2253 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
2254 fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
2255 }
2256 }
2257
2258 static int
2259 fwohci_uid_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *res)
2260 {
2261 int n, rcode;
2262 struct fwohci_uidtbl *fu;
2263
2264 n = (res->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
2265 rcode = (res->fp_hdr[1] & 0x0000f000) >> 12;
2266 if (rcode != IEEE1394_RCODE_COMPLETE ||
2267 sc->sc_uidtbl == NULL ||
2268 n > sc->sc_rootid)
2269 return 0;
2270 fu = &sc->sc_uidtbl[n];
2271 if (arg == 0) {
2272 memcpy(fu->fu_uid, res->fp_iov[0].iov_base, 4);
2273 fu->fu_valid |= 0x1;
2274 } else {
2275 memcpy(fu->fu_uid + 4, res->fp_iov[0].iov_base, 4);
2276 fu->fu_valid |= 0x2;
2277 }
2278 #ifdef FW_DEBUG
2279 if (fw_verbose && fu->fu_valid == 0x3)
2280 printf("fwohci_uid_input: "
2281 "Node %d, UID %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", n,
2282 fu->fu_uid[0], fu->fu_uid[1], fu->fu_uid[2], fu->fu_uid[3],
2283 fu->fu_uid[4], fu->fu_uid[5], fu->fu_uid[6], fu->fu_uid[7]);
2284 #endif
2285 return 0;
2286 }
2287
2288 static int
2289 fwohci_uid_lookup(struct fwohci_softc *sc, const u_int8_t *uid)
2290 {
2291 struct fwohci_uidtbl *fu;
2292 int n;
2293 static const u_int8_t bcast[] =
2294 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2295
2296 fu = sc->sc_uidtbl;
2297 if (fu == NULL) {
2298 notfound:
2299 if (memcmp(uid, bcast, sizeof(bcast)) == 0)
2300 return IEEE1394_BCAST_PHY_ID;
2301 fwohci_uid_collect(sc); /* try to get */
2302 return -1;
2303 }
2304 for (n = 0; ; n++, fu++) {
2305 if (n > sc->sc_rootid)
2306 goto notfound;
2307 if (fu->fu_valid == 0x3 && memcmp(fu->fu_uid, uid, 8) == 0)
2308 break;
2309 }
2310 return n;
2311 }
2312
2313 /*
2314 * functions to support network interface
2315 */
2316 static int
2317 fwohci_if_inreg(struct device *self, u_int32_t offhi, u_int32_t offlo,
2318 void (*handler)(struct device *, struct mbuf *))
2319 {
2320 struct fwohci_softc *sc = (struct fwohci_softc *)self;
2321 int s;
2322
2323 s = splimp();
2324 fwohci_handler_set(sc, IEEE1394_TCODE_WRITE_REQ_BLOCK, offhi, offlo,
2325 fwohci_if_input, handler);
2326 fwohci_handler_set(sc, IEEE1394_TCODE_STREAM_DATA,
2327 sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] & OHCI_NodeId_NodeNumber,
2328 IEEE1394_TAG_GASP, fwohci_if_input, handler);
2329 splx(s);
2330 return 0;
2331 }
2332
2333 static int
2334 fwohci_if_input(struct fwohci_softc *sc, void *arg, struct fwohci_pkt *pkt)
2335 {
2336 int n, len;
2337 struct mbuf *m;
2338 struct iovec *iov;
2339 void (*handler)(struct device *, struct mbuf *) = arg;
2340
2341 #ifdef FW_DEBUG
2342 if (fw_verbose > 1) {
2343 int i;
2344 printf("fwohci_if_input: tcode=0x%x, dlen=%d",
2345 pkt->fp_tcode, pkt->fp_dlen);
2346 if (fw_dump) {
2347 for (i = 0; i < pkt->fp_hlen/4; i++)
2348 printf("%s%08x", i?" ":"\n\t", pkt->fp_hdr[i]);
2349 printf("$");
2350 for (n = 0, len = pkt->fp_dlen; len > 0; len -= i, n++){
2351 iov = &pkt->fp_iov[n];
2352 for (i = 0; i < iov->iov_len; i++)
2353 printf("%s%02x",
2354 (i%32)?((i%4)?"":" "):"\n\t",
2355 ((u_int8_t *)iov->iov_base)[i]);
2356 printf("$");
2357 }
2358 }
2359 printf("\n");
2360 }
2361 #endif /* FW_DEBUG */
2362 len = pkt->fp_dlen;
2363 MGETHDR(m, M_DONTWAIT, MT_DATA);
2364 if (m == NULL)
2365 return IEEE1394_RCODE_COMPLETE;
2366 m->m_len = 16;
2367 if (len + m->m_len > MHLEN) {
2368 MCLGET(m, M_DONTWAIT);
2369 if ((m->m_flags & M_EXT) == 0) {
2370 m_freem(m);
2371 return IEEE1394_RCODE_COMPLETE;
2372 }
2373 }
2374 n = (pkt->fp_hdr[1] >> 16) & OHCI_NodeId_NodeNumber;
2375 if (sc->sc_uidtbl == NULL || n > sc->sc_rootid ||
2376 sc->sc_uidtbl[n].fu_valid != 0x3) {
2377 printf("%s: packet from unknown node: phy id %d\n",
2378 sc->sc_sc1394.sc1394_dev.dv_xname, n);
2379 m_freem(m);
2380 return IEEE1394_RCODE_COMPLETE;
2381 }
2382 memcpy(mtod(m, caddr_t), sc->sc_uidtbl[n].fu_uid, 8);
2383 if (pkt->fp_tcode == IEEE1394_TCODE_STREAM_DATA) {
2384 m->m_flags |= M_BCAST;
2385 mtod(m, u_int32_t *)[2] = mtod(m, u_int32_t *)[3] = 0;
2386 } else {
2387 mtod(m, u_int32_t *)[2] = htonl(pkt->fp_hdr[1]);
2388 mtod(m, u_int32_t *)[3] = htonl(pkt->fp_hdr[2]);
2389 }
2390 mtod(m, u_int8_t *)[8] = n; /*XXX: node id for debug */
2391 mtod(m, u_int8_t *)[9] =
2392 (*pkt->fp_trail >> (16 + OHCI_CTXCTL_SPD_BITPOS)) &
2393 ((1 << OHCI_CTXCTL_SPD_BITLEN) - 1);
2394
2395 m->m_pkthdr.rcvif = NULL; /* set in child */
2396 m->m_pkthdr.len = len + m->m_len;
2397 /*
2398 * We may use receive buffer by external mbuf instead of copy here.
2399 * But asynchronous receive buffer must be operate in buffer fill
2400 * mode, so that each receive buffer will shared by multiple mbufs.
2401 * If upper layer doesn't free mbuf soon, e.g. application program
2402 * is suspended, buffer must be reallocated.
2403 * Isochronous buffer must be operate in packet buffer mode, and
2404 * it is easy to map receive buffer to external mbuf. But it is
2405 * used for broadcast/multicast only, and is expected not so
2406 * performance sensitive for now.
2407 * XXX: The performance may be important for multicast case,
2408 * so we should revisit here later.
2409 * -- onoe
2410 */
2411 n = 0;
2412 iov = pkt->fp_uio.uio_iov;
2413 while (len > 0) {
2414 memcpy(mtod(m, caddr_t) + m->m_len, iov->iov_base,
2415 iov->iov_len);
2416 m->m_len += iov->iov_len;
2417 len -= iov->iov_len;
2418 iov++;
2419 }
2420 (*handler)(sc->sc_sc1394.sc1394_if, m);
2421 return IEEE1394_RCODE_COMPLETE;
2422 }
2423
2424 static int
2425 fwohci_if_output(struct device *self, struct mbuf *m0,
2426 void (*callback)(struct device *, struct mbuf *))
2427 {
2428 struct fwohci_softc *sc = (struct fwohci_softc *)self;
2429 struct fwohci_pkt pkt;
2430 u_int8_t *p;
2431 int s, n, error, spd, hdrlen, maxrec;
2432
2433 p = mtod(m0, u_int8_t *);
2434 if (m0->m_flags & (M_BCAST | M_MCAST)) {
2435 spd = IEEE1394_SPD_S100; /*XXX*/
2436 maxrec = 512; /*XXX*/
2437 hdrlen = 8;
2438 } else {
2439 n = fwohci_uid_lookup(sc, p);
2440 if (n < 0) {
2441 printf("%s: nodeid unknown:"
2442 " %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
2443 sc->sc_sc1394.sc1394_dev.dv_xname,
2444 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
2445 error = EHOSTUNREACH;
2446 goto end;
2447 }
2448 if (n == IEEE1394_BCAST_PHY_ID) {
2449 printf("%s: broadcast with !M_MCAST\n",
2450 sc->sc_sc1394.sc1394_dev.dv_xname);
2451 #ifdef FW_DEBUG
2452 if (fw_dump) {
2453 struct mbuf *m;
2454 printf("packet:");
2455 for (m = m0; m != NULL; m = m->m_next) {
2456 for (n = 0; n < m->m_len; n++)
2457 printf("%s%02x", (n%32)?
2458 ((n%4)?"":" "):"\n\t",
2459 mtod(m, u_int8_t *)[n]);
2460 printf("$");
2461 }
2462 printf("\n");
2463 }
2464 #endif
2465 error = EHOSTUNREACH;
2466 goto end;
2467 }
2468 maxrec = 2 << p[8];
2469 spd = p[9];
2470 hdrlen = 0;
2471 }
2472 if (spd > sc->sc_sc1394.sc1394_link_speed) {
2473 #ifdef FW_DEBUG
2474 if (fw_verbose)
2475 printf("fwohci_if_output: spd (%d) is faster than %d\n",
2476 spd, sc->sc_sc1394.sc1394_link_speed);
2477 #endif
2478 spd = sc->sc_sc1394.sc1394_link_speed;
2479 }
2480 if (maxrec > (512 << spd)) {
2481 #ifdef FW_DEBUG
2482 if (fw_verbose)
2483 printf("fwohci_if_output: maxrec (%d) is larger for"
2484 " spd (%d)\n", maxrec, spd);
2485 #endif
2486 maxrec = 512 << spd;
2487 }
2488 while (maxrec > sc->sc_sc1394.sc1394_max_receive) {
2489 #ifdef FW_DEBUG
2490 if (fw_verbose)
2491 printf("fwohci_if_output: maxrec (%d) is larger than"
2492 " %d\n", maxrec, sc->sc_sc1394.sc1394_max_receive);
2493 #endif
2494 maxrec >>= 1;
2495 }
2496 if (maxrec < 512) {
2497 #ifdef FW_DEBUG
2498 if (fw_verbose)
2499 printf("fwohci_if_output: maxrec (%d) is smaller"
2500 " than minimum\n", maxrec);
2501 #endif
2502 maxrec = 512;
2503 }
2504
2505 m_adj(m0, 16 - hdrlen);
2506 if (m0->m_pkthdr.len > maxrec) {
2507 #ifdef FW_DEBUG
2508 if (fw_verbose)
2509 printf("fwohci_if_output: packet too big:"
2510 " hdr %d, pktlen %d, maxrec %d\n",
2511 hdrlen, m0->m_pkthdr.len, maxrec);
2512 #endif
2513 error = E2BIG; /*XXX*/
2514 goto end;
2515 }
2516
2517 memset(&pkt, 0, sizeof(pkt));
2518 pkt.fp_uio.uio_iov = pkt.fp_iov;
2519 pkt.fp_uio.uio_segflg = UIO_SYSSPACE;
2520 pkt.fp_uio.uio_rw = UIO_WRITE;
2521 s = splimp();
2522 if (m0->m_flags & (M_BCAST | M_MCAST)) {
2523 /* construct GASP header */
2524 p = mtod(m0, u_int8_t *);
2525 p[0] = sc->sc_nodeid >> 8;
2526 p[1] = sc->sc_nodeid & 0xff;
2527 p[2] = 0x00; p[3] = 0x00; p[4] = 0x5e;
2528 p[5] = 0x00; p[6] = 0x00; p[7] = 0x01;
2529 pkt.fp_tcode = IEEE1394_TCODE_STREAM_DATA;
2530 pkt.fp_hlen = 8;
2531 pkt.fp_hdr[0] = (spd << 16) | (IEEE1394_TAG_GASP << 14) |
2532 ((sc->sc_csr[CSR_SB_BROADCAST_CHANNEL] &
2533 OHCI_NodeId_NodeNumber) << 8);
2534 pkt.fp_hdr[1] = m0->m_pkthdr.len << 16;
2535 } else {
2536 pkt.fp_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK;
2537 pkt.fp_hlen = 16;
2538 pkt.fp_hdr[0] = 0x00800100 | (sc->sc_tlabel << 10) |
2539 (spd << 16);
2540 pkt.fp_hdr[1] =
2541 (((sc->sc_nodeid & OHCI_NodeId_BusNumber) | n) << 16) |
2542 (p[10] << 8) | p[11];
2543 pkt.fp_hdr[2] = (p[12]<<24) | (p[13]<<16) | (p[14]<<8) | p[15];
2544 pkt.fp_hdr[3] = m0->m_pkthdr.len << 16;
2545 sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f;
2546 }
2547 pkt.fp_hdr[0] |= (pkt.fp_tcode << 4);
2548 pkt.fp_dlen = m0->m_pkthdr.len;
2549 pkt.fp_m = m0;
2550 pkt.fp_callback = callback;
2551 error = fwohci_at_output(sc, sc->sc_ctx_atrq, &pkt);
2552 splx(s);
2553 m0 = pkt.fp_m;
2554 end:
2555 if (m0 != NULL) {
2556 if (callback)
2557 (*callback)(sc->sc_sc1394.sc1394_if, m0);
2558 else
2559 m_freem(m0);
2560 }
2561 return error;
2562 }
2563