1/* $NetBSD: fwohci.c,v 1.141 2016/11/21 01:19:35 riastradh Exp $ */
2
3/*-
4 * Copyright (c) 2003 Hidetoshi Shimokawa
5 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
6 * All rights reserved.
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 acknowledgement as bellow:
18 *
19 * This product includes software developed by K. Kobayashi and H. Shimokawa
20 *
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 *
36 * $FreeBSD: src/sys/dev/firewire/fwohci.c,v 1.98 2009/02/13 17:44:07 sbruno Exp $
37 *
38 */
39#include <sys/cdefs.h>
40__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.141 2016/11/21 01:19:35 riastradh Exp $");
41
42#include <sys/param.h>
43#include <sys/atomic.h>
44#include <sys/bus.h>
45#include <sys/device.h>
46#include <sys/errno.h>
47#include <sys/conf.h>
48#include <sys/kernel.h>
49#include <sys/malloc.h>
50#include <sys/mbuf.h>
51#include <sys/proc.h>
52#include <sys/reboot.h>
53#include <sys/select.h>
54#include <sys/sysctl.h>
55#include <sys/systm.h>
56
57#include <dev/ieee1394/firewire.h>
58#include <dev/ieee1394/firewirereg.h>
59#include <dev/ieee1394/fwdma.h>
60#include <dev/ieee1394/fwohcireg.h>
61#include <dev/ieee1394/fwohcivar.h>
62#include <dev/ieee1394/firewire_phy.h>
63
64#include "ioconf.h"
65
66#undef OHCI_DEBUG
67
68static int nocyclemaster = 0;
69int firewire_phydma_enable = 1;
70/*
71 * Setup sysctl(3) MIB, hw.fwohci.*
72 *
73 * TBD condition CTLFLAG_PERMANENT on being a module or not
74 */
75SYSCTL_SETUP(sysctl_fwohci, "sysctl fwohci(4) subtree setup")
76{
77 int rc, fwohci_node_num;
78 const struct sysctlnode *node;
79
80 if ((rc = sysctl_createv(clog, 0, NULL, &node,
81 CTLFLAG_PERMANENT, CTLTYPE_NODE, "fwohci",
82 SYSCTL_DESCR("fwohci controls"),
83 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
84 goto err;
85 }
86 fwohci_node_num = node->sysctl_num;
87
88 /* fwohci no cyclemaster flag */
89 if ((rc = sysctl_createv(clog, 0, NULL, &node,
90 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
91 "nocyclemaster", SYSCTL_DESCR("Do not send cycle start packets"),
92 NULL, 0, &nocyclemaster,
93 0, CTL_HW, fwohci_node_num, CTL_CREATE, CTL_EOL)) != 0) {
94 goto err;
95 }
96
97 /* fwohci physical request DMA enable */
98 if ((rc = sysctl_createv(clog, 0, NULL, &node,
99 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "phydma_enable",
100 SYSCTL_DESCR("Allow physical request DMA from firewire"),
101 NULL, 0, &firewire_phydma_enable,
102 0, CTL_HW, fwohci_node_num, CTL_CREATE, CTL_EOL)) != 0) {
103 goto err;
104 }
105 return;
106
107err:
108 aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
109}
110
111static const char * const dbcode[16] = {
112 "OUTM", "OUTL", "INPM", "INPL", "STOR", "LOAD", "NOP ", "STOP",
113 "", "", "", "", "", "", "", ""
114};
115
116static const char * const dbkey[8] = {
117 "ST0", "ST1", "ST2", "ST3", "UNDEF", "REG", "SYS", "DEV"
118};
119
120static const char * const dbcond[4] = { "NEV", "C=1", "C=0", "ALL" };
121static const char * const fwohcicode[32] = {
122 "No stat", "Undef", "long", "miss Ack err",
123 "FIFO underrun","FIFO overrun", "desc err", "data read err",
124 "data write err","bus reset", "timeout", "tcode err",
125 "Undef", "Undef", "unknown event","flushed",
126 "Undef", "ack complete", "ack pend", "Undef",
127 "ack busy_X", "ack busy_A", "ack busy_B", "Undef",
128 "Undef", "Undef", "Undef", "ack tardy",
129 "Undef", "ack data_err", "ack type_err", ""
130};
131
132#define MAX_SPEED 3
133extern const char *fw_linkspeed[];
134static uint32_t const tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31 };
135
136static const struct tcode_info tinfo[] = {
137/* hdr_len block flag valid_response */
138/* 0 WREQQ */ { 16, FWTI_REQ | FWTI_TLABEL, FWTCODE_WRES },
139/* 1 WREQB */ { 16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_WRES },
140/* 2 WRES */ { 12, FWTI_RES, 0xff },
141/* 3 XXX */ { 0, 0, 0xff },
142/* 4 RREQQ */ { 12, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESQ },
143/* 5 RREQB */ { 16, FWTI_REQ | FWTI_TLABEL, FWTCODE_RRESB },
144/* 6 RRESQ */ { 16, FWTI_RES, 0xff },
145/* 7 RRESB */ { 16, FWTI_RES | FWTI_BLOCK_ASY, 0xff },
146/* 8 CYCS */ { 0, 0, 0xff },
147/* 9 LREQ */ { 16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY, FWTCODE_LRES },
148/* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR, 0xff },
149/* b LRES */ { 16, FWTI_RES | FWTI_BLOCK_ASY, 0xff },
150/* c XXX */ { 0, 0, 0xff },
151/* d XXX */ { 0, 0, 0xff },
152/* e PHY */ { 12, FWTI_REQ, 0xff },
153/* f XXX */ { 0, 0, 0xff }
154};
155
156#define OHCI_WRITE_SIGMASK 0xffff0000
157#define OHCI_READ_SIGMASK 0xffff0000
158
159
160int fwohci_print(void *, const char *);
161
162static int fwohci_ioctl(dev_t, u_long, void *, int, struct lwp *);
163
164static uint32_t fwohci_cyctimer(struct firewire_comm *);
165static uint32_t fwohci_set_bus_manager(struct firewire_comm *, u_int);
166static void fwohci_ibr(struct firewire_comm *);
167static int fwohci_irx_enable(struct firewire_comm *, int);
168static int fwohci_irx_disable(struct firewire_comm *, int);
169static int fwohci_itxbuf_enable(struct firewire_comm *, int);
170static int fwohci_itx_disable(struct firewire_comm *, int);
171static void fwohci_timeout(struct firewire_comm *fc);
172#if BYTE_ORDER == BIG_ENDIAN
173static void fwohci_irx_post(struct firewire_comm *, uint32_t *);
174#endif
175static void fwohci_set_intr(struct firewire_comm *, int);
176
177static uint32_t fwphy_rddata(struct fwohci_softc *, uint32_t);
178static uint32_t fwphy_wrdata(struct fwohci_softc *, uint32_t, uint32_t);
179static int fwohci_probe_phy(struct fwohci_softc *);
180static void fwohci_reset(struct fwohci_softc *);
181static void fwohci_execute_db(struct fwohcidb_tr *, bus_dmamap_t);
182static void fwohci_start(struct fwohci_softc *, struct fwohci_dbch *);
183static void fwohci_start_atq(struct firewire_comm *);
184static void fwohci_start_ats(struct firewire_comm *);
185static void fwohci_txd(struct fwohci_softc *, struct fwohci_dbch *);
186static void fwohci_db_free(struct fwohci_softc *, struct fwohci_dbch *);
187static void fwohci_db_init(struct fwohci_softc *, struct fwohci_dbch *);
188static int fwohci_rx_enable(struct fwohci_softc *, struct fwohci_dbch *);
189static int fwohci_tx_enable(struct fwohci_softc *, struct fwohci_dbch *);
190static int fwohci_next_cycle(struct fwohci_softc *, int);
191#ifdef OHCI_DEBUG
192static void fwohci_dump_intr(struct fwohci_softc *, uint32_t);
193#endif
194static void fwohci_intr_core(struct fwohci_softc *, uint32_t);
195static void fwohci_intr_dma(struct fwohci_softc *, uint32_t);
196static void fwohci_task_sid(struct fwohci_softc *);
197static void fwohci_task_dma(struct fwohci_softc *);
198static void fwohci_tbuf_update(struct fwohci_softc *, int);
199static void fwohci_rbuf_update(struct fwohci_softc *, int);
200static void dump_dma(struct fwohci_softc *, uint32_t);
201static void dump_db(struct fwohci_softc *, uint32_t);
202static void print_db(struct fwohcidb_tr *, struct fwohcidb *, uint32_t,
203 uint32_t);
204static void fwohci_txbufdb(struct fwohci_softc *, int, struct fw_bulkxfer *);
205static int fwohci_add_tx_buf(struct fwohci_dbch *, struct fwohcidb_tr *, int);
206static int fwohci_add_rx_buf(struct fwohci_dbch *, struct fwohcidb_tr *, int,
207 struct fwdma_alloc *);
208static int fwohci_arcv_swap(struct fw_pkt *, int);
209static int fwohci_get_plen(struct fwohci_softc *, struct fwohci_dbch *,
210 struct fw_pkt *);
211static void fwohci_arcv_free_buf(struct fwohci_softc *, struct fwohci_dbch *,
212 struct fwohcidb_tr *, int);
213static void fwohci_arcv(struct fwohci_softc *, struct fwohci_dbch *);
214
215
216/*
217 * memory allocated for DMA programs
218 */
219#define DMA_PROG_ALLOC (8 * PAGE_SIZE)
220
221#define NDB FWMAXQUEUE
222
223#define OHCI_VERSION 0x000
224#define OHCI_ATRETRY 0x008
225#define OHCI_CROMHDR 0x018
226#define OHCI_BUS_OPT 0x020
227#define OHCI_BUSIRMC (1 << 31)
228#define OHCI_BUSCMC (1 << 30)
229#define OHCI_BUSISC (1 << 29)
230#define OHCI_BUSBMC (1 << 28)
231#define OHCI_BUSPMC (1 << 27)
232#define OHCI_BUSFNC \
233 (OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC | OHCI_BUSBMC | OHCI_BUSPMC)
234
235#define OHCI_EUID_HI 0x024
236#define OHCI_EUID_LO 0x028
237
238#define OHCI_CROMPTR 0x034
239#define OHCI_HCCCTL 0x050
240#define OHCI_HCCCTLCLR 0x054
241#define OHCI_AREQHI 0x100
242#define OHCI_AREQHICLR 0x104
243#define OHCI_AREQLO 0x108
244#define OHCI_AREQLOCLR 0x10c
245#define OHCI_PREQHI 0x110
246#define OHCI_PREQHICLR 0x114
247#define OHCI_PREQLO 0x118
248#define OHCI_PREQLOCLR 0x11c
249#define OHCI_PREQUPPER 0x120
250
251#define OHCI_SID_BUF 0x064
252#define OHCI_SID_CNT 0x068
253#define OHCI_SID_ERR (1 << 31)
254#define OHCI_SID_CNT_MASK 0xffc
255
256#define OHCI_IT_STAT 0x090
257#define OHCI_IT_STATCLR 0x094
258#define OHCI_IT_MASK 0x098
259#define OHCI_IT_MASKCLR 0x09c
260
261#define OHCI_IR_STAT 0x0a0
262#define OHCI_IR_STATCLR 0x0a4
263#define OHCI_IR_MASK 0x0a8
264#define OHCI_IR_MASKCLR 0x0ac
265
266#define OHCI_LNKCTL 0x0e0
267#define OHCI_LNKCTLCLR 0x0e4
268
269#define OHCI_PHYACCESS 0x0ec
270#define OHCI_CYCLETIMER 0x0f0
271
272#define OHCI_DMACTL(off) (off)
273#define OHCI_DMACTLCLR(off) (off + 0x04)
274#define OHCI_DMACMD(off) (off + 0x0c)
275#define OHCI_DMAMATCH(off) (off + 0x10)
276
277#define OHCI_ATQOFF 0x180
278#define OHCI_ATQCTL OHCI_ATQOFF
279#define OHCI_ATQCTLCLR (OHCI_ATQOFF + 0x04)
280#define OHCI_ATQCMD (OHCI_ATQOFF + 0x0c)
281#define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10)
282
283#define OHCI_ATSOFF 0x1a0
284#define OHCI_ATSCTL OHCI_ATSOFF
285#define OHCI_ATSCTLCLR (OHCI_ATSOFF + 0x04)
286#define OHCI_ATSCMD (OHCI_ATSOFF + 0x0c)
287#define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10)
288
289#define OHCI_ARQOFF 0x1c0
290#define OHCI_ARQCTL OHCI_ARQOFF
291#define OHCI_ARQCTLCLR (OHCI_ARQOFF + 0x04)
292#define OHCI_ARQCMD (OHCI_ARQOFF + 0x0c)
293#define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10)
294
295#define OHCI_ARSOFF 0x1e0
296#define OHCI_ARSCTL OHCI_ARSOFF
297#define OHCI_ARSCTLCLR (OHCI_ARSOFF + 0x04)
298#define OHCI_ARSCMD (OHCI_ARSOFF + 0x0c)
299#define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10)
300
301#define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH))
302#define OHCI_ITCTL(CH) (OHCI_ITOFF(CH))
303#define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 0x04)
304#define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0x0c)
305
306#define OHCI_IROFF(CH) (0x400 + 0x20 * (CH))
307#define OHCI_IRCTL(CH) (OHCI_IROFF(CH))
308#define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 0x04)
309#define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0x0c)
310#define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10)
311
312#define ATRQ_CH 0
313#define ATRS_CH 1
314#define ARRQ_CH 2
315#define ARRS_CH 3
316#define ITX_CH 4
317#define IRX_CH 36
318
319
320/*
321 * Call fwohci_init before fwohci_attach to initialize the kernel's
322 * data structures well enough that fwohci_detach won't crash, even if
323 * fwohci_attach fails.
324 */
325
326void
327fwohci_init(struct fwohci_softc *sc)
328{
329 sc->fc.arq = &sc->arrq.xferq;
330 sc->fc.ars = &sc->arrs.xferq;
331 sc->fc.atq = &sc->atrq.xferq;
332 sc->fc.ats = &sc->atrs.xferq;
333
334 sc->arrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
335 sc->arrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
336 sc->atrq.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
337 sc->atrs.xferq.psize = roundup2(FWPMAX_S400, PAGE_SIZE);
338
339 sc->arrq.xferq.start = NULL;
340 sc->arrs.xferq.start = NULL;
341 sc->atrq.xferq.start = fwohci_start_atq;
342 sc->atrs.xferq.start = fwohci_start_ats;
343
344 sc->arrq.xferq.buf = NULL;
345 sc->arrs.xferq.buf = NULL;
346 sc->atrq.xferq.buf = NULL;
347 sc->atrs.xferq.buf = NULL;
348
349 sc->arrq.xferq.dmach = -1;
350 sc->arrs.xferq.dmach = -1;
351 sc->atrq.xferq.dmach = -1;
352 sc->atrs.xferq.dmach = -1;
353
354 sc->arrq.ndesc = 1;
355 sc->arrs.ndesc = 1;
356 sc->atrq.ndesc = 8; /* equal to maximum of mbuf chains */
357 sc->atrs.ndesc = 2;
358
359 sc->arrq.ndb = NDB;
360 sc->arrs.ndb = NDB / 2;
361 sc->atrq.ndb = NDB;
362 sc->atrs.ndb = NDB / 2;
363
364 sc->arrq.off = OHCI_ARQOFF;
365 sc->arrs.off = OHCI_ARSOFF;
366 sc->atrq.off = OHCI_ATQOFF;
367 sc->atrs.off = OHCI_ATSOFF;
368
369 sc->fc.tcode = tinfo;
370
371 sc->fc.cyctimer = fwohci_cyctimer;
372 sc->fc.ibr = fwohci_ibr;
373 sc->fc.set_bmr = fwohci_set_bus_manager;
374 sc->fc.ioctl = fwohci_ioctl;
375 sc->fc.irx_enable = fwohci_irx_enable;
376 sc->fc.irx_disable = fwohci_irx_disable;
377
378 sc->fc.itx_enable = fwohci_itxbuf_enable;
379 sc->fc.itx_disable = fwohci_itx_disable;
380 sc->fc.timeout = fwohci_timeout;
381 sc->fc.set_intr = fwohci_set_intr;
382#if BYTE_ORDER == BIG_ENDIAN
383 sc->fc.irx_post = fwohci_irx_post;
384#else
385 sc->fc.irx_post = NULL;
386#endif
387 sc->fc.itx_post = NULL;
388
389 sc->intmask = sc->irstat = sc->itstat = 0;
390
391 fw_init(&sc->fc);
392}
393
394/*
395 * Call fwohci_attach after fwohci_init to initialize the hardware and
396 * attach children.
397 */
398
399int
400fwohci_attach(struct fwohci_softc *sc)
401{
402 uint32_t reg;
403 uint8_t ui[8];
404 int i, mver;
405
406/* OHCI version */
407 reg = OREAD(sc, OHCI_VERSION);
408 mver = (reg >> 16) & 0xff;
409 aprint_normal_dev(sc->fc.dev, "OHCI version %x.%x (ROM=%d)\n",
410 mver, reg & 0xff, (reg >> 24) & 1);
411 if (mver < 1 || mver > 9) {
412 aprint_error_dev(sc->fc.dev, "invalid OHCI version\n");
413 return ENXIO;
414 }
415
416/* Available Isochronous DMA channel probe */
417 OWRITE(sc, OHCI_IT_MASK, 0xffffffff);
418 OWRITE(sc, OHCI_IR_MASK, 0xffffffff);
419 reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK);
420 OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff);
421 OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff);
422 for (i = 0; i < 0x20; i++)
423 if ((reg & (1 << i)) == 0)
424 break;
425 sc->fc.nisodma = i;
426 aprint_normal_dev(sc->fc.dev, "No. of Isochronous channels is %d.\n",
427 i);
428 if (i == 0)
429 return ENXIO;
430
431 for (i = 0; i < sc->fc.nisodma; i++) {
432 sc->fc.it[i] = &sc->it[i].xferq;
433 sc->fc.ir[i] = &sc->ir[i].xferq;
434 sc->it[i].xferq.dmach = i;
435 sc->ir[i].xferq.dmach = i;
436 sc->it[i].ndb = 0;
437 sc->ir[i].ndb = 0;
438 sc->it[i].off = OHCI_ITOFF(i);
439 sc->ir[i].off = OHCI_IROFF(i);
440 }
441
442 fw_init_isodma(&sc->fc);
443
444 sc->fc.config_rom = fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat,
445 CROMSIZE, &sc->crom_dma, CROMSIZE, BUS_DMA_NOWAIT);
446 if (sc->fc.config_rom == NULL) {
447 aprint_error_dev(sc->fc.dev, "config_rom alloc failed.\n");
448 return ENOMEM;
449 }
450
451#if 0
452 memset(sc->fc.config_rom, 0, CROMSIZE);
453 sc->fc.config_rom[1] = 0x31333934;
454 sc->fc.config_rom[2] = 0xf000a002;
455 sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI);
456 sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO);
457 sc->fc.config_rom[5] = 0;
458 sc->fc.config_rom[0] = (4 << 24) | (5 << 16);
459
460 sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4);
461#endif
462
463/* SID recieve buffer must align 2^11 */
464#define OHCI_SIDSIZE (1 << 11)
465 sc->sid_buf = fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat, OHCI_SIDSIZE,
466 &sc->sid_dma, OHCI_SIDSIZE, BUS_DMA_NOWAIT);
467 if (sc->sid_buf == NULL) {
468 aprint_error_dev(sc->fc.dev, "sid_buf alloc failed.");
469 return ENOMEM;
470 }
471
472 fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat, sizeof(uint32_t),
473 &sc->dummy_dma, sizeof(uint32_t), BUS_DMA_NOWAIT);
474 if (sc->dummy_dma.v_addr == NULL) {
475 aprint_error_dev(sc->fc.dev, "dummy_dma alloc failed.");
476 return ENOMEM;
477 }
478
479 fwohci_db_init(sc, &sc->arrq);
480 if ((sc->arrq.flags & FWOHCI_DBCH_INIT) == 0)
481 return ENOMEM;
482
483 fwohci_db_init(sc, &sc->arrs);
484 if ((sc->arrs.flags & FWOHCI_DBCH_INIT) == 0)
485 return ENOMEM;
486
487 fwohci_db_init(sc, &sc->atrq);
488 if ((sc->atrq.flags & FWOHCI_DBCH_INIT) == 0)
489 return ENOMEM;
490
491 fwohci_db_init(sc, &sc->atrs);
492 if ((sc->atrs.flags & FWOHCI_DBCH_INIT) == 0)
493 return ENOMEM;
494
495 sc->fc.eui.hi = OREAD(sc, FWOHCIGUID_H);
496 sc->fc.eui.lo = OREAD(sc, FWOHCIGUID_L);
497 for (i = 0; i < 8; i++)
498 ui[i] = FW_EUI64_BYTE(&sc->fc.eui, i);
499 aprint_normal_dev(sc->fc.dev,
500 "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
501 ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]);
502
503 fwohci_reset(sc);
504
505 sc->fc.bdev =
506 config_found(sc->fc.dev, __UNCONST("ieee1394if"), fwohci_print);
507
508 return 0;
509}
510
511int
512fwohci_detach(struct fwohci_softc *sc, int flags)
513{
514 int i, rv;
515
516 if (sc->fc.bdev != NULL) {
517 rv = config_detach(sc->fc.bdev, flags);
518 if (rv)
519 return rv;
520 }
521 if (sc->sid_buf != NULL)
522 fwdma_free(sc->sid_dma.dma_tag, sc->sid_dma.dma_map,
523 sc->sid_dma.v_addr);
524 if (sc->fc.config_rom != NULL)
525 fwdma_free(sc->crom_dma.dma_tag, sc->crom_dma.dma_map,
526 sc->crom_dma.v_addr);
527
528 fwohci_db_free(sc, &sc->arrq);
529 fwohci_db_free(sc, &sc->arrs);
530 fwohci_db_free(sc, &sc->atrq);
531 fwohci_db_free(sc, &sc->atrs);
532 for (i = 0; i < sc->fc.nisodma; i++) {
533 fwohci_db_free(sc, &sc->it[i]);
534 fwohci_db_free(sc, &sc->ir[i]);
535 }
536
537 fw_destroy_isodma(&sc->fc);
538 fw_destroy(&sc->fc);
539
540 return 0;
541}
542
543int
544fwohci_intr(void *arg)
545{
546 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
547 uint32_t stat, irstat, itstat;
548
549 if (!device_is_active(sc->fc.dev))
550 return 0;
551
552 if (!(sc->intmask & OHCI_INT_EN))
553 /* polling mode? */
554 return 0;
555
556 stat = OREAD(sc, FWOHCI_INTSTAT);
557 if (stat == 0xffffffff) {
558 aprint_error_dev(sc->fc.dev, "device physically ejected?\n");
559 return 0;
560 }
561 if (stat)
562 OWRITE(sc, FWOHCI_INTSTATCLR, stat & ~OHCI_INT_PHY_BUS_R);
563
564 stat &= sc->intmask;
565 if (stat == 0)
566 return 0;
567
568 atomic_swap_32(&sc->intstat, stat);
569 if (stat & OHCI_INT_DMA_IR) {
570 irstat = OREAD(sc, OHCI_IR_STAT);
571 OWRITE(sc, OHCI_IR_STATCLR, irstat);
572 atomic_swap_32(&sc->irstat, irstat);
573 }
574 if (stat & OHCI_INT_DMA_IT) {
575 itstat = OREAD(sc, OHCI_IT_STAT);
576 OWRITE(sc, OHCI_IT_STATCLR, itstat);
577 atomic_swap_32(&sc->itstat, itstat);
578 }
579
580 fwohci_intr_core(sc, stat);
581 return 1;
582}
583
584int
585fwohci_resume(struct fwohci_softc *sc)
586{
587 struct fw_xferq *ir;
588 struct fw_bulkxfer *chunk;
589 int i;
590 extern int firewire_resume(struct firewire_comm *);
591
592 fwohci_reset(sc);
593 /* XXX resume isochronous receive automatically. (how about TX?) */
594 for (i = 0; i < sc->fc.nisodma; i++) {
595 ir = &sc->ir[i].xferq;
596 if ((ir->flag & FWXFERQ_RUNNING) != 0) {
597 aprint_normal_dev(sc->fc.dev,
598 "resume iso receive ch: %d\n", i);
599 ir->flag &= ~FWXFERQ_RUNNING;
600 /* requeue stdma to stfree */
601 while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
602 STAILQ_REMOVE_HEAD(&ir->stdma, link);
603 STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
604 }
605 sc->fc.irx_enable(&sc->fc, i);
606 }
607 }
608
609 firewire_resume(&sc->fc);
610 sc->fc.ibr(&sc->fc);
611 return 0;
612}
613
614int
615fwohci_stop(struct fwohci_softc *sc)
616{
617 u_int i;
618
619 fwohci_set_intr(&sc->fc, 0);
620
621/* Now stopping all DMA channel */
622 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
623 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
624 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
625 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
626
627 for (i = 0; i < sc->fc.nisodma; i++) {
628 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
629 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
630 }
631
632#if 0 /* Let dcons(4) be accessed */
633/* Stop interrupt */
634 OWRITE(sc, FWOHCI_INTMASKCLR,
635 OHCI_INT_EN |
636 OHCI_INT_ERR |
637 OHCI_INT_PHY_SID |
638 OHCI_INT_PHY_INT |
639 OHCI_INT_DMA_ATRQ |
640 OHCI_INT_DMA_ATRS |
641 OHCI_INT_DMA_PRRQ |
642 OHCI_INT_DMA_PRRS |
643 OHCI_INT_DMA_ARRQ |
644 OHCI_INT_DMA_ARRS |
645 OHCI_INT_PHY_BUS_R);
646
647/* FLUSH FIFO and reset Transmitter/Reciever */
648 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
649#endif
650
651/* XXX Link down? Bus reset? */
652 return 0;
653}
654
655
656static int
657fwohci_ioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *td)
658{
659 struct fwohci_softc *sc;
660 struct fw_reg_req_t *reg = (struct fw_reg_req_t *)data;
661 uint32_t *dmach = (uint32_t *)data;
662 int err = 0;
663
664 sc = device_lookup_private(&fwohci_cd, DEV2UNIT(dev));
665 if (sc == NULL)
666 return ENXIO;
667
668 if (!data)
669 return EINVAL;
670
671 switch (cmd) {
672 case FWOHCI_WRREG:
673#define OHCI_MAX_REG 0x800
674 if (reg->addr <= OHCI_MAX_REG) {
675 OWRITE(sc, reg->addr, reg->data);
676 reg->data = OREAD(sc, reg->addr);
677 } else
678 err = EINVAL;
679 break;
680
681 case FWOHCI_RDREG:
682 if (reg->addr <= OHCI_MAX_REG)
683 reg->data = OREAD(sc, reg->addr);
684 else
685 err = EINVAL;
686 break;
687
688/* Read DMA descriptors for debug */
689 case DUMPDMA:
690 if (*dmach <= OHCI_MAX_DMA_CH) {
691 dump_dma(sc, *dmach);
692 dump_db(sc, *dmach);
693 } else
694 err = EINVAL;
695 break;
696
697/* Read/Write Phy registers */
698#define OHCI_MAX_PHY_REG 0xf
699 case FWOHCI_RDPHYREG:
700 if (reg->addr <= OHCI_MAX_PHY_REG)
701 reg->data = fwphy_rddata(sc, reg->addr);
702 else
703 err = EINVAL;
704 break;
705
706 case FWOHCI_WRPHYREG:
707 if (reg->addr <= OHCI_MAX_PHY_REG)
708 reg->data = fwphy_wrdata(sc, reg->addr, reg->data);
709 else
710 err = EINVAL;
711 break;
712
713 default:
714 err = EINVAL;
715 break;
716 }
717 return err;
718}
719
720int
721fwohci_print(void *aux, const char *pnp)
722{
723 struct fw_attach_args *fwa = (struct fw_attach_args *)aux;
724
725 if (pnp)
726 aprint_normal("%s at %s", fwa->name, pnp);
727
728 return UNCONF;
729}
730
731
732static uint32_t
733fwohci_cyctimer(struct firewire_comm *fc)
734{
735 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
736
737 return OREAD(sc, OHCI_CYCLETIMER);
738}
739
740static uint32_t
741fwohci_set_bus_manager(struct firewire_comm *fc, u_int node)
742{
743 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
744 uint32_t bm;
745 int i;
746
747#define OHCI_CSR_DATA 0x0c
748#define OHCI_CSR_COMP 0x10
749#define OHCI_CSR_CONT 0x14
750#define OHCI_BUS_MANAGER_ID 0
751
752 OWRITE(sc, OHCI_CSR_DATA, node);
753 OWRITE(sc, OHCI_CSR_COMP, 0x3f);
754 OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID);
755 for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++)
756 DELAY(10);
757 bm = OREAD(sc, OHCI_CSR_DATA);
758 if ((bm & 0x3f) == 0x3f)
759 bm = node;
760 if (firewire_debug)
761 printf("fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i);
762
763 return bm;
764}
765
766static void
767fwohci_ibr(struct firewire_comm *fc)
768{
769 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
770 uint32_t fun;
771
772 aprint_normal_dev(fc->dev, "Initiate bus reset\n");
773
774 /*
775 * Make sure our cached values from the config rom are
776 * initialised.
777 */
778 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
779 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
780
781 /*
782 * Set root hold-off bit so that non cyclemaster capable node
783 * shouldn't became the root node.
784 */
785#if 1
786 fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
787 fun |= FW_PHY_IBR | FW_PHY_RHB;
788 fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
789#else /* Short bus reset */
790 fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
791 fun |= FW_PHY_ISBR | FW_PHY_RHB;
792 fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
793#endif
794}
795
796static int
797fwohci_irx_enable(struct firewire_comm *fc, int dmach)
798{
799 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
800 struct fwohci_dbch *dbch;
801 struct fwohcidb_tr *db_tr;
802 struct fw_bulkxfer *first, *prev, *chunk, *txfer;
803 struct fw_xferq *ir;
804 uint32_t stat;
805 unsigned short tag, ich;
806 int err = 0, ldesc;
807
808 dbch = &sc->ir[dmach];
809 ir = &dbch->xferq;
810
811 if ((ir->flag & FWXFERQ_RUNNING) == 0) {
812 tag = (ir->flag >> 6) & 3;
813 ich = ir->flag & 0x3f;
814 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
815
816 ir->queued = 0;
817 dbch->ndb = ir->bnpacket * ir->bnchunk;
818 dbch->ndesc = 2;
819 fwohci_db_init(sc, dbch);
820 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
821 return ENOMEM;
822 err = fwohci_rx_enable(sc, dbch);
823 if (err)
824 return err;
825 }
826
827 first = STAILQ_FIRST(&ir->stfree);
828 if (first == NULL) {
829 aprint_error_dev(fc->dev, "IR DMA no free chunk\n");
830 return 0;
831 }
832
833 ldesc = dbch->ndesc - 1;
834 prev = NULL;
835 STAILQ_FOREACH(txfer, &ir->stdma, link)
836 prev = txfer;
837 while ((chunk = STAILQ_FIRST(&ir->stfree)) != NULL) {
838 struct fwohcidb *db;
839
840 if (chunk->mbuf != NULL) {
841 db_tr = (struct fwohcidb_tr *)(chunk->start);
842 db_tr->dbcnt = 1;
843 err = bus_dmamap_load_mbuf(fc->dmat, db_tr->dma_map,
844 chunk->mbuf, BUS_DMA_NOWAIT);
845 if (err == 0)
846 fwohci_execute_db(db_tr, db_tr->dma_map);
847 else
848 aprint_error_dev(fc->dev,
849 "mbuf load failed: %d\n", err);
850 FWOHCI_DMA_SET(db_tr->db[1].db.desc.cmd,
851 OHCI_UPDATE |
852 OHCI_INPUT_LAST |
853 OHCI_INTERRUPT_ALWAYS |
854 OHCI_BRANCH_ALWAYS);
855 }
856 db = ((struct fwohcidb_tr *)(chunk->end))->db;
857 FWOHCI_DMA_WRITE(db[ldesc].db.desc.res, 0);
858 FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
859 if (prev != NULL) {
860 db = ((struct fwohcidb_tr *)(prev->end))->db;
861 FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
862 }
863 STAILQ_REMOVE_HEAD(&ir->stfree, link);
864 STAILQ_INSERT_TAIL(&ir->stdma, chunk, link);
865 prev = chunk;
866 }
867 fwdma_sync_multiseg_all(dbch->am,
868 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
869 stat = OREAD(sc, OHCI_IRCTL(dmach));
870 if (stat & OHCI_CNTL_DMA_ACTIVE)
871 return 0;
872 if (stat & OHCI_CNTL_DMA_RUN) {
873 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
874 aprint_error_dev(fc->dev, "IR DMA overrun (0x%08x)\n", stat);
875 }
876
877 if (firewire_debug)
878 printf("start IR DMA 0x%x\n", stat);
879 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
880 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
881 OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
882 OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
883 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
884 OWRITE(sc, OHCI_IRCMD(dmach),
885 ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
886 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
887 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
888#if 0
889 dump_db(sc, IRX_CH + dmach);
890#endif
891 return err;
892}
893
894static int
895fwohci_irx_disable(struct firewire_comm *fc, int dmach)
896{
897 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
898
899 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
900 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
901 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
902 /* XXX we cannot free buffers until the DMA really stops */
903 kpause("fwirxd", true, hz, NULL);
904 fwohci_db_free(sc, &sc->ir[dmach]);
905 sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
906 return 0;
907}
908
909
910static int
911fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
912{
913 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
914 struct fwohci_dbch *dbch;
915 struct fw_bulkxfer *first, *chunk, *prev, *txfer;
916 struct fw_xferq *it;
917 uint32_t stat;
918 int cycle_match, cycle_now, ldesc, err = 0;
919
920 dbch = &sc->it[dmach];
921 it = &dbch->xferq;
922
923 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
924 dbch->ndb = it->bnpacket * it->bnchunk;
925 dbch->ndesc = 3;
926 fwohci_db_init(sc, dbch);
927 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
928 return ENOMEM;
929
930 err = fwohci_tx_enable(sc, dbch);
931 if (err)
932 return err;
933 }
934
935 ldesc = dbch->ndesc - 1;
936 prev = NULL;
937 STAILQ_FOREACH(txfer, &it->stdma, link)
938 prev = txfer;
939 while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
940 struct fwohcidb *db;
941
942 fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
943 BUS_DMASYNC_PREWRITE);
944 fwohci_txbufdb(sc, dmach, chunk);
945 if (prev != NULL) {
946 db = ((struct fwohcidb_tr *)(prev->end))->db;
947#if 0 /* XXX necessary? */
948 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
949 OHCI_BRANCH_ALWAYS);
950#endif
951#if 0 /* if bulkxfer->npacket changes */
952 db[ldesc].db.desc.depend = db[0].db.desc.depend =
953 ((struct fwohcidb_tr *)(chunk->start))->bus_addr |
954 dbch->ndesc;
955#else
956 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
957 FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
958#endif
959 }
960 STAILQ_REMOVE_HEAD(&it->stvalid, link);
961 STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
962 prev = chunk;
963 }
964 fwdma_sync_multiseg_all(dbch->am,
965 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
966 stat = OREAD(sc, OHCI_ITCTL(dmach));
967 if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
968 printf("stat 0x%x\n", stat);
969
970 if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
971 return 0;
972
973#if 0
974 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
975#endif
976 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
977 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
978 OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
979 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
980
981 first = STAILQ_FIRST(&it->stdma);
982 OWRITE(sc, OHCI_ITCMD(dmach),
983 ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
984 if (firewire_debug > 1) {
985 printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
986#if 1
987 dump_dma(sc, ITX_CH + dmach);
988#endif
989 }
990 if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
991#if 1
992 /* Don't start until all chunks are buffered */
993 if (STAILQ_FIRST(&it->stfree) != NULL)
994 goto out;
995#endif
996#if 1
997 /* Clear cycle match counter bits */
998 OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
999
1000 /* 2bit second + 13bit cycle */
1001 cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1002 cycle_match = fwohci_next_cycle(sc, cycle_now);
1003
1004 OWRITE(sc, OHCI_ITCTL(dmach),
1005 OHCI_CNTL_CYCMATCH_S | (cycle_match << 16) |
1006 OHCI_CNTL_DMA_RUN);
1007#else
1008 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1009#endif
1010 if (firewire_debug > 1) {
1011 printf("cycle_match: 0x%04x->0x%04x\n",
1012 cycle_now, cycle_match);
1013 dump_dma(sc, ITX_CH + dmach);
1014 dump_db(sc, ITX_CH + dmach);
1015 }
1016 } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1017 aprint_error_dev(fc->dev, "IT DMA underrun (0x%08x)\n", stat);
1018 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1019 }
1020out:
1021 return err;
1022}
1023
1024static int
1025fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1026{
1027 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1028
1029 OWRITE(sc, OHCI_ITCTLCLR(dmach),
1030 OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S);
1031 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1032 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1033 /* XXX we cannot free buffers until the DMA really stops */
1034 kpause("fwitxd", true, hz, NULL);
1035 fwohci_db_free(sc, &sc->it[dmach]);
1036 sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1037 return 0;
1038}
1039
1040static void
1041fwohci_timeout(struct firewire_comm *fc)
1042{
1043#if 0
1044 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1045#endif
1046 /* nothing? */
1047}
1048
1049#if BYTE_ORDER == BIG_ENDIAN
1050static void
1051fwohci_irx_post (struct firewire_comm *fc, uint32_t *qld)
1052{
1053
1054 qld[0] = FWOHCI_DMA_READ(qld[0]);
1055 return;
1056}
1057#endif
1058
1059static void
1060fwohci_set_intr(struct firewire_comm *fc, int enable)
1061{
1062 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1063
1064 if (firewire_debug)
1065 printf("fwohci_set_intr: %d\n", enable);
1066 if (enable) {
1067 sc->intmask |= OHCI_INT_EN;
1068 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
1069 } else {
1070 sc->intmask &= ~OHCI_INT_EN;
1071 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
1072 }
1073}
1074
1075/*
1076 * Communication with PHY device
1077 */
1078/* XXX need lock for phy access */
1079static uint32_t
1080fwphy_rddata(struct fwohci_softc *sc, u_int addr)
1081{
1082 uint32_t fun, stat;
1083 u_int i, retry = 0;
1084
1085 addr &= 0xf;
1086#define MAX_RETRY 100
1087again:
1088 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL);
1089 fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
1090 OWRITE(sc, OHCI_PHYACCESS, fun);
1091 for (i = 0; i < MAX_RETRY; i++) {
1092 fun = OREAD(sc, OHCI_PHYACCESS);
1093 if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
1094 break;
1095 DELAY(100);
1096 }
1097 if (i >= MAX_RETRY) {
1098 if (firewire_debug)
1099 printf("phy read failed(1).\n");
1100 if (++retry < MAX_RETRY) {
1101 DELAY(100);
1102 goto again;
1103 }
1104 }
1105 /* Make sure that SCLK is started */
1106 stat = OREAD(sc, FWOHCI_INTSTAT);
1107 if ((stat & OHCI_INT_REG_FAIL) != 0 ||
1108 ((fun >> PHYDEV_REGADDR) & 0xf) != addr) {
1109 if (firewire_debug)
1110 printf("phy read failed(2).\n");
1111 if (++retry < MAX_RETRY) {
1112 DELAY(100);
1113 goto again;
1114 }
1115 }
1116 if (firewire_debug || retry >= MAX_RETRY)
1117 aprint_error_dev(sc->fc.dev,
1118 "fwphy_rddata: 0x%x loop=%d, retry=%d\n",
1119 addr, i, retry);
1120#undef MAX_RETRY
1121 return (fun >> PHYDEV_RDDATA) & 0xff;
1122}
1123
1124static uint32_t
1125fwphy_wrdata(struct fwohci_softc *sc, uint32_t addr, uint32_t data)
1126{
1127 uint32_t fun;
1128
1129 addr &= 0xf;
1130 data &= 0xff;
1131
1132 fun =
1133 (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA));
1134 OWRITE(sc, OHCI_PHYACCESS, fun);
1135 DELAY(100);
1136
1137 return fwphy_rddata(sc, addr);
1138}
1139
1140static int
1141fwohci_probe_phy(struct fwohci_softc *sc)
1142{
1143 uint32_t reg, reg2;
1144 int e1394a = 1;
1145
1146/*
1147 * probe PHY parameters
1148 * 0. to prove PHY version, whether compliance of 1394a.
1149 * 1. to probe maximum speed supported by the PHY and
1150 * number of port supported by core-logic.
1151 * It is not actually available port on your PC .
1152 */
1153 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
1154 DELAY(500);
1155
1156 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
1157
1158 if ((reg >> 5) != 7) {
1159 sc->fc.mode &= ~FWPHYASYST;
1160 sc->fc.nport = reg & FW_PHY_NP;
1161 sc->fc.speed = reg & FW_PHY_SPD >> 6;
1162 if (sc->fc.speed > MAX_SPEED) {
1163 aprint_error_dev(sc->fc.dev,
1164 "invalid speed %d (fixed to %d).\n",
1165 sc->fc.speed, MAX_SPEED);
1166 sc->fc.speed = MAX_SPEED;
1167 }
1168 aprint_normal_dev(sc->fc.dev, "Phy 1394 only %s, %d ports.\n",
1169 fw_linkspeed[sc->fc.speed], sc->fc.nport);
1170 } else {
1171 reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
1172 sc->fc.mode |= FWPHYASYST;
1173 sc->fc.nport = reg & FW_PHY_NP;
1174 sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
1175 if (sc->fc.speed > MAX_SPEED) {
1176 aprint_error_dev(sc->fc.dev,
1177 "invalid speed %d (fixed to %d).\n",
1178 sc->fc.speed, MAX_SPEED);
1179 sc->fc.speed = MAX_SPEED;
1180 }
1181 aprint_normal_dev(sc->fc.dev,
1182 "Phy 1394a available %s, %d ports.\n",
1183 fw_linkspeed[sc->fc.speed], sc->fc.nport);
1184
1185 /* check programPhyEnable */
1186 reg2 = fwphy_rddata(sc, 5);
1187#if 0
1188 if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
1189#else /* XXX force to enable 1394a */
1190 if (e1394a) {
1191#endif
1192 if (firewire_debug)
1193 printf("Enable 1394a Enhancements\n");
1194 /* enable EAA EMC */
1195 reg2 |= 0x03;
1196 /* set aPhyEnhanceEnable */
1197 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
1198 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
1199 }
1200#if 0
1201 else {
1202 /* for safe */
1203 reg2 &= ~0x83;
1204 }
1205#endif
1206 reg2 = fwphy_wrdata(sc, 5, reg2);
1207 }
1208
1209 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
1210 if ((reg >> 5) == 7) {
1211 reg = fwphy_rddata(sc, 4);
1212 reg |= 1 << 6;
1213 fwphy_wrdata(sc, 4, reg);
1214 reg = fwphy_rddata(sc, 4);
1215 }
1216 return 0;
1217}
1218
1219static void
1220fwohci_reset(struct fwohci_softc *sc)
1221{
1222 struct fwohcidb_tr *db_tr;
1223 uint32_t reg, reg2;
1224 int i, max_rec, speed;
1225
1226 /* Disable interrupts */
1227 OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
1228
1229 /* Now stopping all DMA channels */
1230 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1231 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1232 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1233 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1234
1235 OWRITE(sc, OHCI_IR_MASKCLR, ~0);
1236 for (i = 0; i < sc->fc.nisodma; i++) {
1237 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1238 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1239 }
1240
1241 /* FLUSH FIFO and reset Transmitter/Reciever */
1242 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1243 if (firewire_debug)
1244 printf("resetting OHCI...");
1245 i = 0;
1246 while (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
1247 if (i++ > 100)
1248 break;
1249 DELAY(1000);
1250 }
1251 if (firewire_debug)
1252 printf("done (loop=%d)\n", i);
1253
1254 /* Probe phy */
1255 fwohci_probe_phy(sc);
1256
1257 /* Probe link */
1258 reg = OREAD(sc, OHCI_BUS_OPT);
1259 reg2 = reg | OHCI_BUSFNC;
1260 max_rec = (reg & 0x0000f000) >> 12;
1261 speed = (reg & 0x00000007);
1262 aprint_normal_dev(sc->fc.dev, "Link %s, max_rec %d bytes.\n",
1263 fw_linkspeed[speed], MAXREC(max_rec));
1264 /* XXX fix max_rec */
1265 sc->fc.maxrec = sc->fc.speed + 8;
1266 if (max_rec != sc->fc.maxrec) {
1267 reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12);
1268 aprint_normal_dev(sc->fc.dev, "max_rec %d -> %d\n",
1269 MAXREC(max_rec), MAXREC(sc->fc.maxrec));
1270 }
1271 if (firewire_debug)
1272 printf("BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
1273 OWRITE(sc, OHCI_BUS_OPT, reg2);
1274
1275 /* Initialize registers */
1276 OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
1277 OWRITE(sc, OHCI_CROMPTR, sc->crom_dma.bus_addr);
1278 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
1279 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
1280 OWRITE(sc, OHCI_SID_BUF, sc->sid_dma.bus_addr);
1281 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
1282
1283 /* Enable link */
1284 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
1285
1286 /* Force to start async RX DMA */
1287 sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING;
1288 sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING;
1289 fwohci_rx_enable(sc, &sc->arrq);
1290 fwohci_rx_enable(sc, &sc->arrs);
1291
1292 /* Initialize async TX */
1293 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
1294 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
1295
1296 /* AT Retries */
1297 OWRITE(sc, FWOHCI_RETRY,
1298 /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */
1299 (0xffff << 16) | (0x0f << 8) | (0x0f << 4) | 0x0f);
1300
1301 sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq);
1302 sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq);
1303 sc->atrq.bottom = sc->atrq.top;
1304 sc->atrs.bottom = sc->atrs.top;
1305
1306 for (i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb;
1307 i++, db_tr = STAILQ_NEXT(db_tr, link))
1308 db_tr->xfer = NULL;
1309 for (i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb;
1310 i++, db_tr = STAILQ_NEXT(db_tr, link))
1311 db_tr->xfer = NULL;
1312
1313
1314 /* Enable interrupts */
1315 sc->intmask = (OHCI_INT_ERR | OHCI_INT_PHY_SID
1316 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1317 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1318 | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
1319 sc->intmask |= OHCI_INT_DMA_IR | OHCI_INT_DMA_IT;
1320 sc->intmask |= OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT;
1321 OWRITE(sc, FWOHCI_INTMASK, sc->intmask);
1322 fwohci_set_intr(&sc->fc, 1);
1323}
1324
1325#define LAST_DB(dbtr) \
1326 &dbtr->db[(dbtr->dbcnt > 2) ? (dbtr->dbcnt - 1) : 0];
1327
1328static void
1329fwohci_execute_db(struct fwohcidb_tr *db_tr, bus_dmamap_t dmamap)
1330{
1331 struct fwohcidb *db;
1332 bus_dma_segment_t *s;
1333 int i;
1334
1335 db = &db_tr->db[db_tr->dbcnt];
1336 for (i = 0; i < dmamap->dm_nsegs; i++) {
1337 s = &dmamap->dm_segs[i];
1338 FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr);
1339 FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len);
1340 FWOHCI_DMA_WRITE(db->db.desc.res, 0);
1341 db++;
1342 db_tr->dbcnt++;
1343 }
1344}
1345
1346static void
1347fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1348{
1349 struct fw_xfer *xfer;
1350 struct fw_pkt *fp;
1351 struct fwohci_txpkthdr *ohcifp;
1352 struct fwohcidb_tr *db_tr, *kick;
1353 struct fwohcidb *db;
1354 uint32_t *ld;
1355 int tcode, hdr_len, pl_off, fsegment = -1, i;
1356 const struct tcode_info *info;
1357 static int maxdesc = 0;
1358
1359 KASSERT(mutex_owned(&dbch->xferq.q_mtx));
1360
1361#if DIAGNOSTIC
1362 if (dbch->off != OHCI_ATQOFF &&
1363 dbch->off != OHCI_ATSOFF)
1364 panic("not async tx");
1365#endif
1366
1367 if (dbch->flags & FWOHCI_DBCH_FULL)
1368 return;
1369
1370 db_tr = dbch->top;
1371 kick = db_tr;
1372 if (dbch->pdb_tr != NULL) {
1373 kick = dbch->pdb_tr;
1374 fwdma_sync_multiseg(dbch->am, kick->idx, kick->idx,
1375 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1376 }
1377txloop:
1378 xfer = STAILQ_FIRST(&dbch->xferq.q);
1379 if (xfer == NULL)
1380 goto kick;
1381#if 0
1382 if (dbch->xferq.queued == 0)
1383 aprint_error_dev(sc->fc.dev, "TX queue empty\n");
1384#endif
1385 STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
1386 db_tr->xfer = xfer;
1387 xfer->flag = FWXF_START;
1388
1389 fp = &xfer->send.hdr;
1390 tcode = fp->mode.common.tcode;
1391
1392 ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
1393 info = &tinfo[tcode];
1394 hdr_len = pl_off = info->hdr_len;
1395
1396 ld = ohcifp->mode.ld;
1397 ld[0] = ld[1] = ld[2] = ld[3] = 0;
1398 for (i = 0; i < pl_off / 4; i++)
1399 ld[i] = fp->mode.ld[i];
1400
1401 ohcifp->mode.common.spd = xfer->send.spd & 0x7;
1402 if (tcode == FWTCODE_STREAM) {
1403 hdr_len = 8;
1404 ohcifp->mode.stream.len = fp->mode.stream.len;
1405 } else if (tcode == FWTCODE_PHY) {
1406 hdr_len = 12;
1407 ld[1] = fp->mode.ld[1];
1408 ld[2] = fp->mode.ld[2];
1409 ohcifp->mode.common.spd = 0;
1410 ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
1411 } else {
1412 ohcifp->mode.asycomm.dst = fp->mode.hdr.dst;
1413 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
1414 ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
1415 }
1416 db = db_tr->db;
1417 FWOHCI_DMA_WRITE(db->db.desc.cmd,
1418 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len);
1419 FWOHCI_DMA_WRITE(db->db.desc.addr, 0);
1420 FWOHCI_DMA_WRITE(db->db.desc.res, 0);
1421/* Specify bound timer of asy. responce */
1422 if (dbch->off != OHCI_ATSOFF)
1423 FWOHCI_DMA_WRITE(db->db.desc.res,
1424 (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13));
1425#if BYTE_ORDER == BIG_ENDIAN
1426 if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ)
1427 hdr_len = 12;
1428 for (i = 0; i < hdr_len / 4; i++)
1429 FWOHCI_DMA_WRITE(ld[i], ld[i]);
1430#endif
1431
1432again:
1433 db_tr->dbcnt = 2;
1434 db = &db_tr->db[db_tr->dbcnt];
1435 if (xfer->send.pay_len > 0) {
1436 int err;
1437 /* handle payload */
1438 if (xfer->mbuf == NULL)
1439 err = bus_dmamap_load(sc->fc.dmat, db_tr->dma_map,
1440 xfer->send.payload, xfer->send.pay_len, NULL,
1441 BUS_DMA_WAITOK);
1442 else {
1443 /* XXX we can handle only 6 (=8-2) mbuf chains */
1444 err = bus_dmamap_load_mbuf(sc->fc.dmat, db_tr->dma_map,
1445 xfer->mbuf, BUS_DMA_WAITOK);
1446 if (err == EFBIG) {
1447 struct mbuf *m0;
1448
1449 if (firewire_debug)
1450 printf("EFBIG.\n");
1451 m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1452 if (m0 != NULL) {
1453 m_copydata(xfer->mbuf, 0,
1454 xfer->mbuf->m_pkthdr.len,
1455 mtod(m0, void *));
1456 m0->m_len = m0->m_pkthdr.len =
1457 xfer->mbuf->m_pkthdr.len;
1458 m_freem(xfer->mbuf);
1459 xfer->mbuf = m0;
1460 goto again;
1461 }
1462 aprint_error_dev(sc->fc.dev,
1463 "m_getcl failed.\n");
1464 }
1465 }
1466 if (!err)
1467 fwohci_execute_db(db_tr, db_tr->dma_map);
1468 else
1469 aprint_error_dev(sc->fc.dev,
1470 "dmamap_load: err=%d\n", err);
1471 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
1472 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
1473#if 0 /* OHCI_OUTPUT_MODE == 0 */
1474 for (i = 2; i < db_tr->dbcnt; i++)
1475 FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd,
1476 OHCI_OUTPUT_MORE);
1477#endif
1478 }
1479 if (maxdesc < db_tr->dbcnt) {
1480 maxdesc = db_tr->dbcnt;
1481 if (firewire_debug)
1482 printf("maxdesc: %d\n", maxdesc);
1483 }
1484 /* last db */
1485 db = LAST_DB(db_tr);
1486 FWOHCI_DMA_SET(db->db.desc.cmd,
1487 OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1488 FWOHCI_DMA_WRITE(db->db.desc.depend,
1489 STAILQ_NEXT(db_tr, link)->bus_addr);
1490
1491 if (fsegment == -1)
1492 fsegment = db_tr->dbcnt;
1493 if (dbch->pdb_tr != NULL) {
1494 db = LAST_DB(dbch->pdb_tr);
1495 FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt);
1496 }
1497 dbch->xferq.queued++;
1498 dbch->pdb_tr = db_tr;
1499 db_tr = STAILQ_NEXT(db_tr, link);
1500 if (db_tr != dbch->bottom)
1501 goto txloop;
1502 else {
1503 aprint_error_dev(sc->fc.dev, "fwohci_start: lack of db_trq\n");
1504 dbch->flags |= FWOHCI_DBCH_FULL;
1505 }
1506kick:
1507 /* kick asy q */
1508 fwdma_sync_multiseg(dbch->am, kick->idx, dbch->pdb_tr->idx,
1509 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1510
1511 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1512 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE);
1513 else {
1514 if (firewire_debug)
1515 printf("start AT DMA status=%x\n",
1516 OREAD(sc, OHCI_DMACTL(dbch->off)));
1517 OWRITE(sc, OHCI_DMACMD(dbch->off),
1518 dbch->top->bus_addr | fsegment);
1519 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN);
1520 dbch->xferq.flag |= FWXFERQ_RUNNING;
1521 }
1522
1523 dbch->top = db_tr;
1524 return;
1525}
1526
1527static void
1528fwohci_start_atq(struct firewire_comm *fc)
1529{
1530 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1531 struct fwohci_dbch *dbch = &sc->atrq;
1532
1533 mutex_enter(&dbch->xferq.q_mtx);
1534 fwohci_start(sc, dbch);
1535 mutex_exit(&dbch->xferq.q_mtx);
1536 return;
1537}
1538
1539static void
1540fwohci_start_ats(struct firewire_comm *fc)
1541{
1542 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1543 struct fwohci_dbch *dbch = &sc->atrs;
1544
1545 mutex_enter(&dbch->xferq.q_mtx);
1546 fwohci_start(sc, dbch);
1547 mutex_exit(&dbch->xferq.q_mtx);
1548 return;
1549}
1550
1551static void
1552fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1553{
1554 struct firewire_comm *fc = &sc->fc;
1555 struct fwohcidb_tr *tr;
1556 struct fwohcidb *db;
1557 struct fw_xfer *xfer;
1558 u_int stat, status;
1559 int packets = 0, ch, err = 0;
1560
1561#if DIAGNOSTIC
1562 if (dbch->off != OHCI_ATQOFF &&
1563 dbch->off != OHCI_ATSOFF)
1564 panic("not async tx");
1565#endif
1566 if (dbch->off == OHCI_ATQOFF)
1567 ch = ATRQ_CH;
1568 else /* OHCI_ATSOFF */
1569 ch = ATRS_CH;
1570
1571 mutex_enter(&dbch->xferq.q_mtx);
1572 tr = dbch->bottom;
1573 while (dbch->xferq.queued > 0) {
1574 fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx,
1575 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1576 db = LAST_DB(tr);
1577 status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT;
1578 if (!(status & OHCI_CNTL_DMA_ACTIVE))
1579 if (fc->status != FWBUSINIT)
1580 goto out;
1581 if (tr->xfer->send.pay_len > 0) {
1582 bus_dmamap_sync(fc->dmat, tr->dma_map,
1583 0, tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1584 bus_dmamap_unload(fc->dmat, tr->dma_map);
1585 }
1586#if 1
1587 if (firewire_debug > 1)
1588 dump_db(sc, ch);
1589#endif
1590 if (status & OHCI_CNTL_DMA_DEAD) {
1591 /* Stop DMA */
1592 OWRITE(sc, OHCI_DMACTLCLR(dbch->off),
1593 OHCI_CNTL_DMA_RUN);
1594 aprint_error_dev(fc->dev, "force reset AT FIFO\n");
1595 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
1596 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
1597 OWRITE(sc, OHCI_DMACTLCLR(dbch->off),
1598 OHCI_CNTL_DMA_RUN);
1599 }
1600 stat = status & FWOHCIEV_MASK;
1601 switch(stat) {
1602 case FWOHCIEV_ACKPEND:
1603
1604 /* FALLTHROUGH */
1605
1606 case FWOHCIEV_ACKCOMPL:
1607 err = 0;
1608 break;
1609
1610 case FWOHCIEV_ACKBSA:
1611 case FWOHCIEV_ACKBSB:
1612 case FWOHCIEV_ACKBSX:
1613 aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat,
1614 fwohcicode[stat]);
1615 err = EBUSY;
1616 break;
1617
1618 case FWOHCIEV_FLUSHED:
1619 case FWOHCIEV_ACKTARD:
1620 aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat,
1621 fwohcicode[stat]);
1622 err = EAGAIN;
1623 break;
1624
1625 case FWOHCIEV_MISSACK:
1626 case FWOHCIEV_UNDRRUN:
1627 case FWOHCIEV_OVRRUN:
1628 case FWOHCIEV_DESCERR:
1629 case FWOHCIEV_DTRDERR:
1630 case FWOHCIEV_TIMEOUT:
1631 case FWOHCIEV_TCODERR:
1632 case FWOHCIEV_UNKNOWN:
1633 case FWOHCIEV_ACKDERR:
1634 case FWOHCIEV_ACKTERR:
1635 default:
1636 aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat,
1637 fwohcicode[stat]);
1638 err = EINVAL;
1639 break;
1640 }
1641 dbch->xferq.queued--;
1642 dbch->bottom = STAILQ_NEXT(tr, link);
1643 if (tr->xfer != NULL) {
1644 xfer = tr->xfer;
1645 tr->xfer = NULL;
1646 mutex_exit(&dbch->xferq.q_mtx);
1647 if (xfer->flag & FWXF_RCVD) {
1648#if 0
1649 if (firewire_debug)
1650 printf("already rcvd\n");
1651#endif
1652 fw_xfer_done(xfer);
1653 } else {
1654 microtime(&xfer->tv);
1655 xfer->flag = FWXF_SENT;
1656 if (err == EBUSY) {
1657 xfer->flag = FWXF_BUSY;
1658 xfer->resp = err;
1659 xfer->recv.pay_len = 0;
1660 fw_xfer_done(xfer);
1661 } else if (stat != FWOHCIEV_ACKPEND) {
1662 if (stat != FWOHCIEV_ACKCOMPL)
1663 xfer->flag = FWXF_SENTERR;
1664 xfer->resp = err;
1665 xfer->recv.pay_len = 0;
1666 fw_xfer_done(xfer);
1667 }
1668 }
1669 mutex_enter(&dbch->xferq.q_mtx);
1670 /*
1671 * The watchdog timer takes care of split
1672 * transcation timeout for ACKPEND case.
1673 */
1674 } else
1675 aprint_error_dev(fc->dev, "this shouldn't happen\n");
1676 packets++;
1677 if (dbch->bottom == dbch->top) {
1678 /* we reaches the end of context program */
1679 if (firewire_debug && dbch->xferq.queued > 0)
1680 printf("queued > 0\n");
1681 break;
1682 }
1683 tr = dbch->bottom;
1684 }
1685out:
1686 if (dbch->xferq.queued > 0 || packets > 0)
1687 fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx,
1688 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1689 if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
1690 aprint_normal_dev(fc->dev, "make free slot\n");
1691 dbch->flags &= ~FWOHCI_DBCH_FULL;
1692 fwohci_start(sc, dbch);
1693 }
1694 mutex_exit(&dbch->xferq.q_mtx);
1695}
1696
1697static void
1698fwohci_db_free(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1699{
1700 struct fwohcidb_tr *db_tr, *last;
1701
1702 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1703 return;
1704
1705 for (last = db_tr = STAILQ_FIRST(&dbch->db_trq); db_tr != last;
1706 db_tr = STAILQ_NEXT(db_tr, link)) {
1707 bus_dmamap_destroy(sc->fc.dmat, db_tr->dma_map);
1708 if ((dbch->xferq.flag & FWXFERQ_EXTBUF) == 0 &&
1709 db_tr->buf != NULL) {
1710 fwdma_free(sc->fc.dmat, db_tr->dma_map, db_tr->buf);
1711 db_tr->buf = NULL;
1712 }
1713 }
1714 dbch->ndb = 0;
1715 db_tr = STAILQ_FIRST(&dbch->db_trq);
1716 fwdma_free_multiseg(dbch->am);
1717 free(db_tr, M_FW);
1718 STAILQ_INIT(&dbch->db_trq);
1719 dbch->flags &= ~FWOHCI_DBCH_INIT;
1720 seldestroy(&dbch->xferq.rsel);
1721}
1722
1723static void
1724fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1725{
1726 struct firewire_comm *fc = &sc->fc;
1727 struct fwohcidb_tr *db_tr, *lastq, *tmpq;
1728 int idb;
1729 const int db_tr_sz = sizeof(struct fwohcidb_tr) * dbch->ndb;
1730
1731 if ((dbch->flags & FWOHCI_DBCH_INIT) != 0)
1732 goto out;
1733
1734 /* allocate DB entries and attach one to each DMA channels */
1735 /* DB entry must start at 16 bytes bounary. */
1736 STAILQ_INIT(&dbch->db_trq);
1737 db_tr = (struct fwohcidb_tr *)malloc(db_tr_sz, M_FW, M_WAITOK | M_ZERO);
1738 if (db_tr == NULL) {
1739 aprint_error_dev(fc->dev, "malloc(1) failed\n");
1740 return;
1741 }
1742
1743#define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1744 dbch->am = fwdma_malloc_multiseg(fc, DB_SIZE(dbch), DB_SIZE(dbch),
1745#if 0
1746 dbch->ndb, BUS_DMA_WAITOK);
1747#else /* Ooops, debugging now... */
1748 dbch->ndb, BUS_DMA_WAITOK |
1749 (dbch->off == OHCI_ARQOFF || dbch->off == OHCI_ARSOFF) ?
1750 BUS_DMA_COHERENT : 0);
1751#endif
1752 if (dbch->am == NULL) {
1753 aprint_error_dev(fc->dev, "fwdma_malloc_multiseg failed\n");
1754 free(db_tr, M_FW);
1755 return;
1756 }
1757 /* Attach DB to DMA ch. */
1758 for (idb = 0; idb < dbch->ndb; idb++) {
1759 db_tr->idx = idb;
1760 db_tr->dbcnt = 0;
1761 db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb);
1762 db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb);
1763 /* create dmamap for buffers */
1764#define MAX_REQCOUNT 0xffff
1765 if (bus_dmamap_create(fc->dmat, dbch->xferq.psize,
1766 dbch->ndesc > 3 ? dbch->ndesc - 2 : 1, MAX_REQCOUNT, 0,
1767 0, &db_tr->dma_map) != 0) {
1768 aprint_error_dev(fc->dev, "bus_dmamap_create failed\n");
1769 dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1770 fwohci_db_free(sc, dbch);
1771 return;
1772 }
1773 if (dbch->off == OHCI_ARQOFF ||
1774 dbch->off == OHCI_ARSOFF) {
1775 db_tr->buf = fwdma_malloc(fc->dev, fc->dmat,
1776 &db_tr->dma_map, dbch->xferq.psize, 1,
1777 BUS_DMA_NOWAIT);
1778 if (db_tr->buf == NULL) {
1779 aprint_error_dev(fc->dev,
1780 "fwdma_malloc failed\n");
1781 dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1782 fwohci_db_free(sc, dbch);
1783 return;
1784 }
1785 }
1786 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1787 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1788 struct fw_bulkxfer *bulkxfer =
1789 &dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket];
1790
1791 if (idb % dbch->xferq.bnpacket == 0)
1792 bulkxfer->start = (void *)db_tr;
1793 if ((idb + 1) % dbch->xferq.bnpacket == 0)
1794 bulkxfer->end = (void *)db_tr;
1795 }
1796 db_tr++;
1797 }
1798 lastq = NULL;
1799 STAILQ_FOREACH(tmpq, &dbch->db_trq, link)
1800 lastq = tmpq;
1801 lastq->link.stqe_next = STAILQ_FIRST(&dbch->db_trq);
1802out:
1803 dbch->xferq.queued = 0;
1804 dbch->pdb_tr = NULL;
1805 dbch->top = STAILQ_FIRST(&dbch->db_trq);
1806 dbch->bottom = dbch->top;
1807 dbch->flags = FWOHCI_DBCH_INIT;
1808 selinit(&dbch->xferq.rsel);
1809}
1810
1811static int
1812fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1813{
1814 int err = 0;
1815 int idb, z, i, dmach = 0, ldesc;
1816 struct fwohcidb_tr *db_tr;
1817 struct fwohcidb *db;
1818
1819 if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) {
1820 err = EINVAL;
1821 return err;
1822 }
1823 z = dbch->ndesc;
1824 for (dmach = 0; dmach < sc->fc.nisodma; dmach++)
1825 if (dbch->off == sc->it[dmach].off)
1826 break;
1827 if (dmach == sc->fc.nisodma) {
1828 err = EINVAL;
1829 return err;
1830 }
1831 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1832 return err;
1833 dbch->xferq.flag |= FWXFERQ_RUNNING;
1834 for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++)
1835 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1836 db_tr = dbch->top;
1837 for (idb = 0; idb < dbch->ndb; idb++) {
1838 fwohci_add_tx_buf(dbch, db_tr, idb);
1839 if (STAILQ_NEXT(db_tr, link) == NULL)
1840 break;
1841 db = db_tr->db;
1842 ldesc = db_tr->dbcnt - 1;
1843 FWOHCI_DMA_WRITE(db[0].db.desc.depend,
1844 STAILQ_NEXT(db_tr, link)->bus_addr | z);
1845 db[ldesc].db.desc.depend = db[0].db.desc.depend;
1846 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1847 if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1848 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1849 OHCI_INTERRUPT_ALWAYS);
1850 /* OHCI 1.1 and above */
1851 FWOHCI_DMA_SET(db[0].db.desc.cmd,
1852 OHCI_INTERRUPT_ALWAYS);
1853 }
1854 }
1855 db_tr = STAILQ_NEXT(db_tr, link);
1856 }
1857 FWOHCI_DMA_CLEAR(
1858 dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf);
1859 return err;
1860}
1861
1862static int
1863fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1864{
1865 struct fwohcidb_tr *db_tr;
1866 struct fwohcidb *db;
1867 int idb, z, i, ldesc, err = 0;
1868
1869 z = dbch->ndesc;
1870 if (dbch->xferq.flag & FWXFERQ_STREAM) {
1871 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1872 return err;
1873 } else
1874 if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1875 err = EBUSY;
1876 return err;
1877 }
1878 dbch->xferq.flag |= FWXFERQ_RUNNING;
1879 dbch->top = STAILQ_FIRST(&dbch->db_trq);
1880 for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++)
1881 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1882 db_tr = dbch->top;
1883 if (db_tr->dbcnt != 0)
1884 goto run;
1885 for (idb = 0; idb < dbch->ndb; idb++) {
1886 if (dbch->off == OHCI_ARQOFF ||
1887 dbch->off == OHCI_ARSOFF)
1888 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
1889 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
1890 fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma);
1891 if (STAILQ_NEXT(db_tr, link) == NULL)
1892 break;
1893 db = db_tr->db;
1894 ldesc = db_tr->dbcnt - 1;
1895 FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend,
1896 STAILQ_NEXT(db_tr, link)->bus_addr | z);
1897 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1898 if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1899 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1900 OHCI_INTERRUPT_ALWAYS);
1901 FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1902 }
1903 }
1904 db_tr = STAILQ_NEXT(db_tr, link);
1905 }
1906 FWOHCI_DMA_CLEAR(dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend,
1907 0xf);
1908 dbch->buf_offset = 0;
1909run:
1910 fwdma_sync_multiseg_all(dbch->am,
1911 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1912 if (!(dbch->xferq.flag & FWXFERQ_STREAM)) {
1913 OWRITE(sc, OHCI_DMACMD(dbch->off), dbch->top->bus_addr | z);
1914 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN);
1915 }
1916 return err;
1917}
1918
1919static int
1920fwohci_next_cycle(struct fwohci_softc *sc, int cycle_now)
1921{
1922 int sec, cycle, cycle_match;
1923
1924 cycle = cycle_now & 0x1fff;
1925 sec = cycle_now >> 13;
1926#define CYCLE_MOD 0x10
1927#if 1
1928#define CYCLE_DELAY 8 /* min delay to start DMA */
1929#else
1930#define CYCLE_DELAY 7000 /* min delay to start DMA */
1931#endif
1932 cycle = cycle + CYCLE_DELAY;
1933 if (cycle >= 8000) {
1934 sec++;
1935 cycle -= 8000;
1936 }
1937 cycle = roundup2(cycle, CYCLE_MOD);
1938 if (cycle >= 8000) {
1939 sec++;
1940 if (cycle == 8000)
1941 cycle = 0;
1942 else
1943 cycle = CYCLE_MOD;
1944 }
1945 cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1946
1947 return cycle_match;
1948}
1949
1950#ifdef OHCI_DEBUG
1951static void
1952fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1953{
1954
1955 if (stat & OREAD(sc, FWOHCI_INTMASK))
1956 print("%s: INTERRUPT"
1957 " < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>"
1958 " 0x%08x, 0x%08x\n",
1959 device_xname(fc->dev),
1960 stat & OHCI_INT_EN ? "DMA_EN ":"",
1961 stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1962 stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1963 stat & OHCI_INT_ERR ? "INT_ERR ":"",
1964 stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1965 stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1966 stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1967 stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1968 stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1969 stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1970 stat & OHCI_INT_PHY_SID ? "SID ":"",
1971 stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1972 stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1973 stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1974 stat & OHCI_INT_DMA_IT ? "DMA_IT " :"",
1975 stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"",
1976 stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"",
1977 stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"",
1978 stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"",
1979 stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"",
1980 stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"",
1981 stat, OREAD(sc, FWOHCI_INTMASK)
1982 );
1983}
1984#endif
1985
1986static void
1987fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat)
1988{
1989 struct firewire_comm *fc = &sc->fc;
1990 uint32_t node_id, plen;
1991
1992 if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1993 fc->status = FWBUSRESET;
1994 /* Disable bus reset interrupt until sid recv. */
1995 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1996
1997 aprint_normal_dev(fc->dev, "BUS reset\n");
1998 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1999 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
2000
2001 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
2002 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
2003 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
2004 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
2005
2006 fw_busreset(&sc->fc, FWBUSRESET);
2007 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2008 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2009 }
2010 if (stat & OHCI_INT_PHY_SID) {
2011 /* Enable bus reset interrupt */
2012 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
2013 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
2014
2015 /* Allow async. request to us */
2016 OWRITE(sc, OHCI_AREQHI, 1 << 31);
2017 if (firewire_phydma_enable) {
2018 /* allow from all nodes */
2019 OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
2020 OWRITE(sc, OHCI_PREQLO, 0xffffffff);
2021 /* 0 to 4GB region */
2022 OWRITE(sc, OHCI_PREQUPPER, 0x10000);
2023 }
2024 /* Set ATRetries register */
2025 OWRITE(sc, OHCI_ATRETRY, 1<<(13+16) | 0xfff);
2026
2027 /*
2028 * Checking whether the node is root or not. If root, turn on
2029 * cycle master.
2030 */
2031 node_id = OREAD(sc, FWOHCI_NODEID);
2032 plen = OREAD(sc, OHCI_SID_CNT);
2033
2034 fc->nodeid = node_id & 0x3f;
2035 aprint_normal_dev(fc->dev, "node_id=0x%08x, gen=%d, ",
2036 node_id, (plen >> 16) & 0xff);
2037 if (!(node_id & OHCI_NODE_VALID)) {
2038 aprint_error_dev(fc->dev, "Bus reset failure\n");
2039 goto sidout;
2040 }
2041
2042 /* cycle timer */
2043 sc->cycle_lost = 0;
2044 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
2045 if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
2046 aprint_normal("CYCLEMASTER mode\n");
2047 OWRITE(sc, OHCI_LNKCTL,
2048 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
2049 } else {
2050 aprint_normal("non CYCLEMASTER mode\n");
2051 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
2052 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
2053 }
2054
2055 fc->status = FWBUSINIT;
2056
2057 fwohci_task_sid(sc);
2058 }
2059sidout:
2060 if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)))
2061 fwohci_task_dma(sc);
2062}
2063
2064static void
2065fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat)
2066{
2067 struct firewire_comm *fc = &sc->fc;
2068 uint32_t irstat, itstat;
2069 u_int i;
2070
2071 if (stat & OHCI_INT_DMA_IR) {
2072 irstat = atomic_swap_32(&sc->irstat, 0);
2073 for (i = 0; i < fc->nisodma; i++)
2074 if ((irstat & (1 << i)) != 0) {
2075 struct fwohci_dbch *dbch = &sc->ir[i];
2076
2077 if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
2078 aprint_error_dev(fc->dev,
2079 "dma(%d) not active\n", i);
2080 continue;
2081 }
2082 fwohci_rbuf_update(sc, i);
2083 }
2084 }
2085 if (stat & OHCI_INT_DMA_IT) {
2086 itstat = atomic_swap_32(&sc->itstat, 0);
2087 for (i = 0; i < fc->nisodma; i++)
2088 if ((itstat & (1 << i)) != 0)
2089 fwohci_tbuf_update(sc, i);
2090 }
2091 if (stat & OHCI_INT_DMA_PRRS) {
2092#if 0
2093 dump_dma(sc, ARRS_CH);
2094 dump_db(sc, ARRS_CH);
2095#endif
2096 fwohci_arcv(sc, &sc->arrs);
2097 }
2098 if (stat & OHCI_INT_DMA_PRRQ) {
2099#if 0
2100 dump_dma(sc, ARRQ_CH);
2101 dump_db(sc, ARRQ_CH);
2102#endif
2103 fwohci_arcv(sc, &sc->arrq);
2104 }
2105 if (stat & OHCI_INT_CYC_LOST) {
2106 if (sc->cycle_lost >= 0)
2107 sc->cycle_lost++;
2108 if (sc->cycle_lost > 10) {
2109 sc->cycle_lost = -1;
2110#if 0
2111 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
2112#endif
2113 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
2114 aprint_error_dev(fc->dev, "too many cycle lost, "
2115 "no cycle master present?\n");
2116 }
2117 }
2118 if (stat & OHCI_INT_DMA_ATRQ)
2119 fwohci_txd(sc, &(sc->atrq));
2120 if (stat & OHCI_INT_DMA_ATRS)
2121 fwohci_txd(sc, &(sc->atrs));
2122 if (stat & OHCI_INT_PW_ERR)
2123 aprint_error_dev(fc->dev, "posted write error\n");
2124 if (stat & OHCI_INT_ERR)
2125 aprint_error_dev(fc->dev, "unrecoverable error\n");
2126 if (stat & OHCI_INT_PHY_INT)
2127 aprint_normal_dev(fc->dev, "phy int\n");
2128
2129 return;
2130}
2131
2132static void
2133fwohci_task_sid(struct fwohci_softc *sc)
2134{
2135 struct firewire_comm *fc = &sc->fc;
2136 uint32_t *buf;
2137 int i, plen;
2138
2139 plen = OREAD(sc, OHCI_SID_CNT);
2140
2141 if (plen & OHCI_SID_ERR) {
2142 aprint_error_dev(fc->dev, "SID Error\n");
2143 return;
2144 }
2145 plen &= OHCI_SID_CNT_MASK;
2146 if (plen < 4 || plen > OHCI_SIDSIZE) {
2147 aprint_error_dev(fc->dev, "invalid SID len = %d\n", plen);
2148 return;
2149 }
2150 plen -= 4; /* chop control info */
2151 buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2152 if (buf == NULL) {
2153 aprint_error_dev(fc->dev, "malloc failed\n");
2154 return;
2155 }
2156 for (i = 0; i < plen / 4; i++)
2157 buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2158#if 1 /* XXX needed?? */
2159 /* pending all pre-bus_reset packets */
2160 fwohci_txd(sc, &sc->atrq);
2161 fwohci_txd(sc, &sc->atrs);
2162 fwohci_arcv(sc, &sc->arrs);
2163 fwohci_arcv(sc, &sc->arrq);
2164 fw_drain_txq(fc);
2165#endif
2166 fw_sidrcv(fc, buf, plen);
2167 free(buf, M_FW);
2168}
2169
2170static void
2171fwohci_task_dma(struct fwohci_softc *sc)
2172{
2173 uint32_t stat;
2174
2175again:
2176 stat = atomic_swap_32(&sc->intstat, 0);
2177 if (stat)
2178 fwohci_intr_dma(sc, stat);
2179 else
2180 return;
2181 goto again;
2182}
2183
2184static void
2185fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2186{
2187 struct firewire_comm *fc = &sc->fc;
2188 struct fwohcidb *db;
2189 struct fw_bulkxfer *chunk;
2190 struct fw_xferq *it;
2191 uint32_t stat;
2192#if 0
2193 uint32_t count;
2194#endif
2195 int w = 0, ldesc;
2196
2197 it = fc->it[dmach];
2198 ldesc = sc->it[dmach].ndesc - 1;
2199 mutex_enter(&fc->fc_mtx);
2200 fwdma_sync_multiseg_all(sc->it[dmach].am, BUS_DMASYNC_POSTREAD);
2201 if (firewire_debug)
2202 dump_db(sc, ITX_CH + dmach);
2203 while ((chunk = STAILQ_FIRST(&it->stdma)) != NULL) {
2204 db = ((struct fwohcidb_tr *)(chunk->end))->db;
2205 stat =
2206 FWOHCI_DMA_READ(db[ldesc].db.desc.res) >> OHCI_STATUS_SHIFT;
2207 db = ((struct fwohcidb_tr *)(chunk->start))->db;
2208 /* timestamp */
2209#if 0
2210 count =
2211 FWOHCI_DMA_READ(db[ldesc].db.desc.res) & OHCI_COUNT_MASK;
2212#else
2213 (void)FWOHCI_DMA_READ(db[ldesc].db.desc.res);
2214#endif
2215 if (stat == 0)
2216 break;
2217 STAILQ_REMOVE_HEAD(&it->stdma, link);
2218 switch (stat & FWOHCIEV_MASK) {
2219 case FWOHCIEV_ACKCOMPL:
2220#if 0
2221 printf("0x%08x\n", count);
2222#endif
2223 break;
2224 default:
2225 aprint_error_dev(fc->dev,
2226 "Isochronous transmit err %02x(%s)\n",
2227 stat, fwohcicode[stat & 0x1f]);
2228 }
2229 STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2230 w++;
2231 }
2232 if (w)
2233 cv_broadcast(&it->cv);
2234 mutex_exit(&fc->fc_mtx);
2235}
2236
2237static void
2238fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2239{
2240 struct firewire_comm *fc = &sc->fc;
2241 struct fwohcidb_tr *db_tr;
2242 struct fw_bulkxfer *chunk;
2243 struct fw_xferq *ir;
2244 uint32_t stat;
2245 int w = 0, ldesc;
2246
2247 ir = fc->ir[dmach];
2248 ldesc = sc->ir[dmach].ndesc - 1;
2249
2250#if 0
2251 dump_db(sc, dmach);
2252#endif
2253 if ((ir->flag & FWXFERQ_HANDLER) == 0)
2254 mutex_enter(&fc->fc_mtx);
2255 fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2256 while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2257 db_tr = (struct fwohcidb_tr *)chunk->end;
2258 stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res) >>
2259 OHCI_STATUS_SHIFT;
2260 if (stat == 0)
2261 break;
2262
2263 if (chunk->mbuf != NULL) {
2264 bus_dmamap_sync(fc->dmat, db_tr->dma_map, 0,
2265 db_tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
2266 bus_dmamap_unload(fc->dmat, db_tr->dma_map);
2267 } else if (ir->buf != NULL)
2268 fwdma_sync_multiseg(ir->buf, chunk->poffset,
2269 ir->bnpacket, BUS_DMASYNC_POSTREAD);
2270 else
2271 /* XXX */
2272 aprint_error_dev(fc->dev,
2273 "fwohci_rbuf_update: this shouldn't happend\n");
2274
2275 STAILQ_REMOVE_HEAD(&ir->stdma, link);
2276 STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2277 switch (stat & FWOHCIEV_MASK) {
2278 case FWOHCIEV_ACKCOMPL:
2279 chunk->resp = 0;
2280 break;
2281 default:
2282 chunk->resp = EINVAL;
2283 aprint_error_dev(fc->dev,
2284 "Isochronous receive err %02x(%s)\n",
2285 stat, fwohcicode[stat & 0x1f]);
2286 }
2287 w++;
2288 }
2289 if ((ir->flag & FWXFERQ_HANDLER) == 0) {
2290 if (w)
2291 cv_broadcast(&ir->cv);
2292 mutex_exit(&fc->fc_mtx);
2293 }
2294 if (w == 0)
2295 return;
2296 if (ir->flag & FWXFERQ_HANDLER)
2297 ir->hand(ir);
2298}
2299
2300static void
2301dump_dma(struct fwohci_softc *sc, uint32_t ch)
2302{
2303 struct fwohci_dbch *dbch;
2304 uint32_t cntl, stat, cmd, match;
2305
2306 if (ch == ATRQ_CH)
2307 dbch = &sc->atrq;
2308 else if (ch == ATRS_CH)
2309 dbch = &sc->atrs;
2310 else if (ch == ARRQ_CH)
2311 dbch = &sc->arrq;
2312 else if (ch == ARRS_CH)
2313 dbch = &sc->arrs;
2314 else if (ch < IRX_CH)
2315 dbch = &sc->it[ch - ITX_CH];
2316 else
2317 dbch = &sc->ir[ch - IRX_CH];
2318 cntl = stat = OREAD(sc, dbch->off);
2319 cmd = OREAD(sc, dbch->off + 0xc);
2320 match = OREAD(sc, dbch->off + 0x10);
2321
2322 aprint_normal_dev(sc->fc.dev,
2323 "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2324 ch,
2325 cntl,
2326 cmd,
2327 match);
2328 stat &= 0xffff;
2329 if (stat)
2330 aprint_normal_dev(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2331 ch,
2332 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2333 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2334 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2335 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2336 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2337 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2338 fwohcicode[stat & 0x1f],
2339 stat & 0x1f
2340 );
2341 else
2342 aprint_normal_dev(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2343}
2344
2345static void
2346dump_db(struct fwohci_softc *sc, uint32_t ch)
2347{
2348 struct fwohci_dbch *dbch;
2349 struct fwohcidb_tr *cp = NULL, *pp;
2350 struct fwohcidb *curr = NULL;
2351#if 0
2352 struct fwohcidb_tr *np = NULL;
2353 struct fwohcidb *prev, *next = NULL;
2354#endif
2355 int idb, jdb;
2356 uint32_t cmd;
2357
2358 if (ch == ATRQ_CH)
2359 dbch = &sc->atrq;
2360 else if (ch == ATRS_CH)
2361 dbch = &sc->atrs;
2362 else if (ch == ARRQ_CH)
2363 dbch = &sc->arrq;
2364 else if (ch == ARRS_CH)
2365 dbch = &sc->arrs;
2366 else if (ch < IRX_CH)
2367 dbch = &sc->it[ch - ITX_CH];
2368 else
2369 dbch = &sc->ir[ch - IRX_CH];
2370 cmd = OREAD(sc, dbch->off + 0xc);
2371
2372 if (dbch->ndb == 0) {
2373 aprint_error_dev(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2374 return;
2375 }
2376 pp = dbch->top;
2377#if 0
2378 prev = pp->db;
2379#endif
2380 for (idb = 0; idb < dbch->ndb; idb++) {
2381 cp = STAILQ_NEXT(pp, link);
2382 if (cp == NULL) {
2383 curr = NULL;
2384 goto outdb;
2385 }
2386#if 0
2387 np = STAILQ_NEXT(cp, link);
2388#endif
2389 for (jdb = 0; jdb < dbch->ndesc; jdb++)
2390 if ((cmd & 0xfffffff0) == cp->bus_addr) {
2391 curr = cp->db;
2392#if 0
2393 if (np != NULL)
2394 next = np->db;
2395 else
2396 next = NULL;
2397#endif
2398 goto outdb;
2399 }
2400 pp = STAILQ_NEXT(pp, link);
2401 if (pp == NULL) {
2402 curr = NULL;
2403 goto outdb;
2404 }
2405#if 0
2406 prev = pp->db;
2407#endif
2408 }
2409outdb:
2410 if (curr != NULL) {
2411#if 0
2412 aprint_normal("Prev DB %d\n", ch);
2413 print_db(pp, prev, ch, dbch->ndesc);
2414#endif
2415 aprint_normal("Current DB %d\n", ch);
2416 print_db(cp, curr, ch, dbch->ndesc);
2417#if 0
2418 aprint_normal("Next DB %d\n", ch);
2419 print_db(np, next, ch, dbch->ndesc);
2420#endif
2421 } else
2422 aprint_error("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2423 return;
2424}
2425
2426static void
2427print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db, uint32_t ch,
2428 uint32_t hogemax)
2429{
2430 fwohcireg_t stat;
2431 int i, key;
2432 uint32_t cmd, res;
2433
2434 if (db == NULL) {
2435 aprint_error("No Descriptor is found\n");
2436 return;
2437 }
2438
2439 aprint_normal("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2440 ch,
2441 "Current",
2442 "OP ",
2443 "KEY",
2444 "INT",
2445 "BR ",
2446 "len",
2447 "Addr",
2448 "Depend",
2449 "Stat",
2450 "Cnt");
2451 for (i = 0; i <= hogemax; i++) {
2452 cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2453 res = FWOHCI_DMA_READ(db[i].db.desc.res);
2454 key = cmd & OHCI_KEY_MASK;
2455 stat = res >> OHCI_STATUS_SHIFT;
2456 aprint_normal("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2457 (uintmax_t)db_tr->bus_addr,
2458 dbcode[(cmd >> 28) & 0xf],
2459 dbkey[(cmd >> 24) & 0x7],
2460 dbcond[(cmd >> 20) & 0x3],
2461 dbcond[(cmd >> 18) & 0x3],
2462 cmd & OHCI_COUNT_MASK,
2463 FWOHCI_DMA_READ(db[i].db.desc.addr),
2464 FWOHCI_DMA_READ(db[i].db.desc.depend),
2465 stat,
2466 res & OHCI_COUNT_MASK);
2467 if (stat & 0xff00)
2468 aprint_normal(" %s%s%s%s%s%s %s(%x)\n",
2469 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2470 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2471 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2472 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2473 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2474 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2475 fwohcicode[stat & 0x1f],
2476 stat & 0x1f
2477 );
2478 else
2479 aprint_normal(" Nostat\n");
2480 if (key == OHCI_KEY_ST2)
2481 aprint_normal("0x%08x 0x%08x 0x%08x 0x%08x\n",
2482 FWOHCI_DMA_READ(db[i+1].db.immed[0]),
2483 FWOHCI_DMA_READ(db[i+1].db.immed[1]),
2484 FWOHCI_DMA_READ(db[i+1].db.immed[2]),
2485 FWOHCI_DMA_READ(db[i+1].db.immed[3]));
2486 if (key == OHCI_KEY_DEVICE)
2487 return;
2488 if ((cmd & OHCI_BRANCH_MASK) == OHCI_BRANCH_ALWAYS)
2489 return;
2490 if ((cmd & OHCI_CMD_MASK) == OHCI_OUTPUT_LAST)
2491 return;
2492 if ((cmd & OHCI_CMD_MASK) == OHCI_INPUT_LAST)
2493 return;
2494 if (key == OHCI_KEY_ST2)
2495 i++;
2496 }
2497 return;
2498}
2499
2500static void
2501fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2502{
2503 struct fwohcidb_tr *db_tr /*, *fdb_tr */;
2504 struct fwohci_dbch *dbch;
2505 struct fwohcidb *db;
2506 struct fw_pkt *fp;
2507 struct fwohci_txpkthdr *ohcifp;
2508 unsigned short chtag;
2509 int idb;
2510
2511 KASSERT(mutex_owned(&sc->fc.fc_mtx));
2512
2513 dbch = &sc->it[dmach];
2514 chtag = sc->it[dmach].xferq.flag & 0xff;
2515
2516 db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2517/*
2518 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2519aprint_normal(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2520*/
2521 for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2522 db = db_tr->db;
2523 fp = (struct fw_pkt *)db_tr->buf;
2524 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2525 ohcifp->mode.ld[0] = fp->mode.ld[0];
2526 ohcifp->mode.common.spd = 0 & 0x7;
2527 ohcifp->mode.stream.len = fp->mode.stream.len;
2528 ohcifp->mode.stream.chtag = chtag;
2529 ohcifp->mode.stream.tcode = 0xa;
2530#if BYTE_ORDER == BIG_ENDIAN
2531 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2532 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2533#endif
2534
2535 FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2536 FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2537 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2538#if 0 /* if bulkxfer->npackets changes */
2539 db[2].db.desc.cmd =
2540 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS;
2541 db[0].db.desc.depend = db[dbch->ndesc - 1].db.desc.depend =
2542 STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2543#else
2544 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2545 FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2546#endif
2547 bulkxfer->end = (void *)db_tr;
2548 db_tr = STAILQ_NEXT(db_tr, link);
2549 }
2550 db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2551 FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2552 FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2553#if 0 /* if bulkxfer->npackets changes */
2554 db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2555 /* OHCI 1.1 and above */
2556 db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2557#endif
2558/*
2559 db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2560 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2561aprint_normal(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2562*/
2563 return;
2564}
2565
2566static int
2567fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2568 int poffset)
2569{
2570 struct fwohcidb *db = db_tr->db;
2571 struct fw_xferq *it;
2572 int err = 0;
2573
2574 it = &dbch->xferq;
2575 if (it->buf == 0) {
2576 err = EINVAL;
2577 return err;
2578 }
2579 db_tr->buf = fwdma_v_addr(it->buf, poffset);
2580 db_tr->dbcnt = 3;
2581
2582 FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2583 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2584 FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2585 memset((void *)db[1].db.immed, 0, sizeof(db[1].db.immed));
2586 FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2587 fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2588
2589 FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2590 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2591#if 1
2592 FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2593 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2594#endif
2595 return 0;
2596}
2597
2598int
2599fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2600 int poffset, struct fwdma_alloc *dummy_dma)
2601{
2602 struct fwohcidb *db = db_tr->db;
2603 struct fw_xferq *rq;
2604 int i, ldesc;
2605 bus_addr_t dbuf[2];
2606 int dsiz[2];
2607
2608 rq = &dbch->xferq;
2609 if (rq->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2610 /* async */
2611 db_tr->dbcnt = 1;
2612 dsiz[0] = rq->psize;
2613 dbuf[0] = db_tr->dma_map->dm_segs[0].ds_addr;
2614 } else {
2615 /* isoc */
2616 db_tr->dbcnt = 0;
2617 dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2618 dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2619 dsiz[db_tr->dbcnt] = rq->psize;
2620 if (rq->buf != NULL) {
2621 db_tr->buf = fwdma_v_addr(rq->buf, poffset);
2622 dbuf[db_tr->dbcnt] = fwdma_bus_addr(rq->buf, poffset);
2623 }
2624 db_tr->dbcnt++;
2625 }
2626 for (i = 0; i < db_tr->dbcnt; i++) {
2627 FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2628 FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2629 if (rq->flag & FWXFERQ_STREAM)
2630 FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2631 FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2632 }
2633 ldesc = db_tr->dbcnt - 1;
2634 if (rq->flag & FWXFERQ_STREAM)
2635 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2636 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2637 return 0;
2638}
2639
2640
2641static int
2642fwohci_arcv_swap(struct fw_pkt *fp, int len)
2643{
2644 struct fw_pkt *fp0;
2645 uint32_t ld0;
2646 int hlen;
2647#if BYTE_ORDER == BIG_ENDIAN
2648 int slen, i;
2649#endif
2650
2651 ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2652#if 0
2653 printf("ld0: x%08x\n", ld0);
2654#endif
2655 fp0 = (struct fw_pkt *)&ld0;
2656 /* determine length to swap */
2657 switch (fp0->mode.common.tcode) {
2658 case FWTCODE_WRES:
2659 case FWTCODE_RREQQ:
2660 case FWTCODE_WREQQ:
2661 case FWTCODE_RRESQ:
2662 case FWOHCITCODE_PHY:
2663#if BYTE_ORDER == BIG_ENDIAN
2664 slen = 12;
2665#endif
2666 break;
2667
2668 case FWTCODE_RREQB:
2669 case FWTCODE_WREQB:
2670 case FWTCODE_LREQ:
2671 case FWTCODE_RRESB:
2672 case FWTCODE_LRES:
2673#if BYTE_ORDER == BIG_ENDIAN
2674 slen = 16;
2675#endif
2676 break;
2677
2678 default:
2679 aprint_error("Unknown tcode %d\n", fp0->mode.common.tcode);
2680 return 0;
2681 }
2682 hlen = tinfo[fp0->mode.common.tcode].hdr_len;
2683 if (hlen > len) {
2684 if (firewire_debug)
2685 printf("splitted header\n");
2686 return len - hlen;
2687 }
2688#if BYTE_ORDER == BIG_ENDIAN
2689 for (i = 0; i < slen / 4; i++)
2690 fp->mode.ld[i] = FWOHCI_DMA_READ(fp->mode.ld[i]);
2691#endif
2692 return hlen;
2693}
2694
2695static int
2696fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2697 struct fw_pkt *fp)
2698{
2699 const struct tcode_info *info;
2700 int r;
2701
2702 info = &tinfo[fp->mode.common.tcode];
2703 r = info->hdr_len + sizeof(uint32_t);
2704 if (info->flag & FWTI_BLOCK_ASY)
2705 r += roundup2(fp->mode.wreqb.len, sizeof(uint32_t));
2706
2707 if (r == sizeof(uint32_t)) {
2708 /* XXX */
2709 aprint_error_dev(sc->fc.dev, "Unknown tcode %d\n",
2710 fp->mode.common.tcode);
2711 return -1;
2712 }
2713
2714 if (r > dbch->xferq.psize) {
2715 aprint_error_dev(sc->fc.dev, "Invalid packet length %d\n", r);
2716 return -1;
2717 /* panic ? */
2718 }
2719
2720 return r;
2721}
2722
2723static void
2724fwohci_arcv_free_buf(struct fwohci_softc *sc, struct fwohci_dbch *dbch,
2725 struct fwohcidb_tr *db_tr, int wake)
2726{
2727 struct fwohcidb *db = db_tr->db;
2728 struct fwohcidb_tr *bdb_tr = dbch->bottom;
2729
2730 FWOHCI_DMA_CLEAR(db->db.desc.depend, 0xf);
2731 FWOHCI_DMA_WRITE(db->db.desc.res, dbch->xferq.psize);
2732
2733 fwdma_sync_multiseg(dbch->am, bdb_tr->idx, bdb_tr->idx,
2734 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2735 FWOHCI_DMA_SET(bdb_tr->db[0].db.desc.depend, dbch->ndesc);
2736
2737 fwdma_sync_multiseg(dbch->am, bdb_tr->idx, db_tr->idx,
2738 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2739 dbch->bottom = db_tr;
2740
2741 if (wake)
2742 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE);
2743}
2744
2745static void
2746fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
2747{
2748 struct fwohcidb_tr *db_tr;
2749 struct fw_pkt pktbuf, *fp;
2750 struct iovec vec[2];
2751 bus_addr_t m;
2752 bus_size_t n;
2753 u_int spd;
2754 uint32_t stat, status, event;
2755 uint8_t *ld;
2756 int nvec, resCount, len, plen, hlen, offset;
2757 const int psize = dbch->xferq.psize;
2758
2759#if DIAGNOSTIC
2760 if (dbch->off != OHCI_ARQOFF &&
2761 dbch->off != OHCI_ARSOFF)
2762 panic("not async rx");
2763#endif
2764
2765 mutex_enter(&dbch->xferq.q_mtx);
2766 db_tr = dbch->top;
2767 /* XXX we cannot handle a packet which lies in more than two buf */
2768 fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx,
2769 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2770 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >> OHCI_STATUS_SHIFT;
2771 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) & OHCI_COUNT_MASK;
2772 while (status & OHCI_CNTL_DMA_ACTIVE) {
2773#if 0
2774 if (dbch->off == OHCI_ARQOFF)
2775 aprint_normal_dev(sc->fc.dev,
2776 "buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2777 db_tr->bus_addr, status, resCount);
2778#endif
2779 n = 0;
2780 len = psize - resCount;
2781 ld = (uint8_t *)db_tr->buf;
2782 if (dbch->pdb_tr == NULL) {
2783 len -= dbch->buf_offset;
2784 ld += dbch->buf_offset;
2785 m = dbch->buf_offset;
2786 } else
2787 m = 0;
2788 if (len > 0)
2789 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
2790 m, len, BUS_DMASYNC_POSTREAD);
2791 while (len > 0) {
2792 if (dbch->pdb_tr != NULL) {
2793 /* we have a fragment in previous buffer */
2794 int rlen = 0;
2795 void *buf;
2796
2797 if (dbch->buf_offset < 0) {
2798 /* splitted in header, pull up */
2799 char *p;
2800
2801 rlen -= dbch->buf_offset;
2802 buf = (char *)dbch->pdb_tr->buf +
2803 psize - rlen;
2804
2805 KASSERT(rlen <= sizeof(pktbuf));
2806
2807 p = (char *)&pktbuf;
2808 memcpy(p, buf, rlen);
2809 p += rlen;
2810 /* this must be too long but harmless */
2811 rlen = sizeof(pktbuf) - rlen;
2812 memcpy(p, db_tr->buf, rlen);
2813 ld += rlen;
2814 len -= rlen;
2815 hlen = fwohci_arcv_swap(&pktbuf,
2816 sizeof(pktbuf));
2817 if (hlen <= 0) {
2818 aprint_error_dev(sc->fc.dev,
2819 "hlen should be positive.");
2820 goto err;
2821 }
2822 offset = sizeof(pktbuf);
2823 vec[0].iov_base = (char *)&pktbuf;
2824 vec[0].iov_len = offset;
2825 } else {
2826 /* splitted in payload */
2827 buf = (char *)dbch->pdb_tr->buf +
2828 dbch->buf_offset;
2829 rlen = psize - dbch->buf_offset;
2830 if (firewire_debug)
2831 printf("rlen=%d, offset=%d\n",
2832 rlen, dbch->buf_offset);
2833 offset = rlen;
2834 vec[0].iov_base = buf;
2835 vec[0].iov_len = rlen;
2836 }
2837 fp = (struct fw_pkt *)vec[0].iov_base;
2838 nvec = 1;
2839 } else {
2840 /* no fragment in previous buffer */
2841 fp = (struct fw_pkt *)ld;
2842 hlen = fwohci_arcv_swap(fp, len);
2843 if (hlen == 0)
2844 goto err;
2845 if (hlen < 0) {
2846 dbch->pdb_tr = db_tr;
2847 dbch->buf_offset -= psize;
2848 /* sanity check */
2849 if (resCount != 0) {
2850 aprint_error_dev(sc->fc.dev,
2851 "resCount=%d hlen=%d\n",
2852 resCount, hlen);
2853 goto err;
2854 }
2855 goto out;
2856 }
2857 offset = 0;
2858 nvec = 0;
2859 }
2860 plen = fwohci_get_plen(sc, dbch, fp) - offset;
2861 if (plen < 0) {
2862 /*
2863 * minimum header size + trailer =
2864 * sizeof(fw_pkt) so this shouldn't happens
2865 */
2866 aprint_error_dev(sc->fc.dev,
2867 "plen(%d) is negative! offset=%d\n",
2868 plen, offset);
2869 goto err;
2870 }
2871 if (plen > 0) {
2872 len -= plen;
2873 if (len < 0) {
2874 dbch->pdb_tr = db_tr;
2875 if (firewire_debug)
2876 printf("splitted payload\n");
2877 /* sanity check */
2878 if (resCount != 0) {
2879 aprint_error_dev(sc->fc.dev,
2880 "resCount=%d plen=%d"
2881 " len=%d\n",
2882 resCount, plen, len);
2883 goto err;
2884 }
2885 goto out;
2886 }
2887 vec[nvec].iov_base = ld;
2888 vec[nvec].iov_len = plen;
2889 nvec++;
2890 ld += plen;
2891 }
2892 if (nvec == 0)
2893 aprint_error_dev(sc->fc.dev, "nvec == 0\n");
2894
2895/* DMA result-code will be written at the tail of packet */
2896 stat = FWOHCI_DMA_READ(*(uint32_t *)(ld -
2897 sizeof(struct fwohci_trailer)));
2898#if 0
2899 aprint_normal("plen: %d, stat %x\n", plen, stat);
2900#endif
2901 spd = (stat >> 21) & 0x3;
2902 event = (stat >> 16) & 0x1f;
2903 switch (event) {
2904 case FWOHCIEV_ACKPEND:
2905#if 0
2906 aprint_normal(sc->fc.dev,
2907 "ack pending tcode=0x%x..\n",
2908 fp->mode.common.tcode);
2909#endif
2910 /* fall through */
2911 case FWOHCIEV_ACKCOMPL:
2912 {
2913 struct fw_rcv_buf rb;
2914
2915 vec[nvec - 1].iov_len -=
2916 sizeof(struct fwohci_trailer);
2917 if (vec[nvec - 1].iov_len == 0)
2918 nvec--;
2919 rb.fc = &sc->fc;
2920 rb.vec = vec;
2921 rb.nvec = nvec;
2922 rb.spd = spd;
2923 fw_rcv(&rb);
2924 break;
2925 }
2926 case FWOHCIEV_BUSRST:
2927 if ((sc->fc.status != FWBUSRESET) &&
2928 (sc->fc.status != FWBUSINIT))
2929 aprint_error_dev(sc->fc.dev,
2930 "got BUSRST packet!?\n");
2931 break;
2932 default:
2933 aprint_error_dev(sc->fc.dev,
2934 "Async DMA Receive error err=%02x %s"
2935 " plen=%d offset=%d len=%d status=0x%08x"
2936 " tcode=0x%x, stat=0x%08x\n",
2937 event, fwohcicode[event], plen,
2938 (int)(ld - (uint8_t *)db_tr->buf - plen),
2939 len, OREAD(sc, OHCI_DMACTL(dbch->off)),
2940 fp->mode.common.tcode, stat);
2941#if 1 /* XXX */
2942 goto err;
2943#endif
2944 break;
2945 }
2946 if (dbch->pdb_tr != NULL) {
2947 if (dbch->buf_offset < 0)
2948 bus_dmamap_sync(sc->fc.dmat,
2949 dbch->pdb_tr->dma_map,
2950 psize + dbch->buf_offset,
2951 0 - dbch->buf_offset,
2952 BUS_DMASYNC_PREREAD);
2953 else
2954 bus_dmamap_sync(sc->fc.dmat,
2955 dbch->pdb_tr->dma_map,
2956 dbch->buf_offset,
2957 psize - dbch->buf_offset,
2958 BUS_DMASYNC_PREREAD);
2959 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 1);
2960 dbch->pdb_tr = NULL;
2961 }
2962 dbch->buf_offset = ld - (uint8_t *)db_tr->buf;
2963 n += (plen + offset);
2964 }
2965out:
2966 if (n > 0)
2967 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map, m, n,
2968 BUS_DMASYNC_PREREAD);
2969
2970 if (resCount != 0) {
2971 dbch->buf_offset = psize - resCount;
2972 break;
2973 }
2974
2975 /* done on this buffer */
2976
2977 if (dbch->pdb_tr == NULL) {
2978 fwohci_arcv_free_buf(sc, dbch, db_tr, 1);
2979 dbch->buf_offset = 0;
2980 } else
2981 if (dbch->pdb_tr != db_tr)
2982 aprint_error_dev(sc->fc.dev,
2983 "pdb_tr != db_tr\n");
2984 dbch->top = STAILQ_NEXT(db_tr, link);
2985
2986 db_tr = dbch->top;
2987 fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx,
2988 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2989 status = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res) >>
2990 OHCI_STATUS_SHIFT;
2991 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
2992 & OHCI_COUNT_MASK;
2993
2994 /* XXX check buffer overrun */
2995
2996 /* XXX make sure DMA is not dead */
2997 }
2998 fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx,
2999 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3000 mutex_exit(&dbch->xferq.q_mtx);
3001 return;
3002
3003err:
3004 aprint_error_dev(sc->fc.dev, "AR DMA status=%x, ",
3005 OREAD(sc, OHCI_DMACTL(dbch->off)));
3006 if (dbch->pdb_tr != NULL) {
3007 if (dbch->buf_offset < 0)
3008 bus_dmamap_sync(sc->fc.dmat, dbch->pdb_tr->dma_map,
3009 psize + dbch->buf_offset, 0 - dbch->buf_offset,
3010 BUS_DMASYNC_PREREAD);
3011 else
3012 bus_dmamap_sync(sc->fc.dmat, dbch->pdb_tr->dma_map,
3013 dbch->buf_offset, psize - dbch->buf_offset,
3014 BUS_DMASYNC_PREREAD);
3015 fwohci_arcv_free_buf(sc, dbch, dbch->pdb_tr, 1);
3016 dbch->pdb_tr = NULL;
3017 }
3018 /* skip until resCount != 0 */
3019 aprint_error(" skip buffer");
3020 while (resCount == 0) {
3021 aprint_error(" #");
3022 fwohci_arcv_free_buf(sc, dbch, db_tr, 0);
3023 db_tr = STAILQ_NEXT(db_tr, link);
3024 resCount = FWOHCI_DMA_READ(db_tr->db[0].db.desc.res)
3025 & OHCI_COUNT_MASK;
3026 }
3027 aprint_error(" done\n");
3028 dbch->top = db_tr;
3029 dbch->buf_offset = psize - resCount;
3030 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE);
3031 fwdma_sync_multiseg(dbch->am, db_tr->idx, db_tr->idx,
3032 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3033 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
3034 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
3035 mutex_exit(&dbch->xferq.q_mtx);
3036}
3037