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