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