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