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