fwohci.c revision 1.135 1 /* $NetBSD: fwohci.c,v 1.135 2013/09/12 20:16:51 martin 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.135 2013/09/12 20:16:51 martin 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
923 dbch = &sc->it[dmach];
924 it = &dbch->xferq;
925
926 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0) {
927 dbch->ndb = it->bnpacket * it->bnchunk;
928 dbch->ndesc = 3;
929 fwohci_db_init(sc, dbch);
930 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
931 return ENOMEM;
932
933 err = fwohci_tx_enable(sc, dbch);
934 if (err)
935 return err;
936 }
937
938 ldesc = dbch->ndesc - 1;
939 prev = NULL;
940 STAILQ_FOREACH(txfer, &it->stdma, link)
941 prev = txfer;
942 while ((chunk = STAILQ_FIRST(&it->stvalid)) != NULL) {
943 struct fwohcidb *db;
944
945 fwdma_sync_multiseg(it->buf, chunk->poffset, it->bnpacket,
946 BUS_DMASYNC_PREWRITE);
947 fwohci_txbufdb(sc, dmach, chunk);
948 if (prev != NULL) {
949 db = ((struct fwohcidb_tr *)(prev->end))->db;
950 #if 0 /* XXX necessary? */
951 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
952 OHCI_BRANCH_ALWAYS);
953 #endif
954 #if 0 /* if bulkxfer->npacket changes */
955 db[ldesc].db.desc.depend = db[0].db.desc.depend =
956 ((struct fwohcidb_tr *)(chunk->start))->bus_addr |
957 dbch->ndesc;
958 #else
959 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
960 FWOHCI_DMA_SET(db[ldesc].db.desc.depend, dbch->ndesc);
961 #endif
962 }
963 STAILQ_REMOVE_HEAD(&it->stvalid, link);
964 STAILQ_INSERT_TAIL(&it->stdma, chunk, link);
965 prev = chunk;
966 }
967 fwdma_sync_multiseg_all(dbch->am,
968 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
969 stat = OREAD(sc, OHCI_ITCTL(dmach));
970 if (firewire_debug && (stat & OHCI_CNTL_CYCMATCH_S))
971 printf("stat 0x%x\n", stat);
972
973 if (stat & (OHCI_CNTL_DMA_ACTIVE | OHCI_CNTL_CYCMATCH_S))
974 return 0;
975
976 #if 0
977 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
978 #endif
979 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
980 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
981 OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
982 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
983
984 first = STAILQ_FIRST(&it->stdma);
985 OWRITE(sc, OHCI_ITCMD(dmach),
986 ((struct fwohcidb_tr *)(first->start))->bus_addr | dbch->ndesc);
987 if (firewire_debug > 1) {
988 printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat);
989 #if 1
990 dump_dma(sc, ITX_CH + dmach);
991 #endif
992 }
993 if ((stat & OHCI_CNTL_DMA_RUN) == 0) {
994 #if 1
995 /* Don't start until all chunks are buffered */
996 if (STAILQ_FIRST(&it->stfree) != NULL)
997 goto out;
998 #endif
999 #if 1
1000 /* Clear cycle match counter bits */
1001 OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xffff0000);
1002
1003 /* 2bit second + 13bit cycle */
1004 cycle_now = (fc->cyctimer(fc) >> 12) & 0x7fff;
1005 cycle_match = fwohci_next_cycle(sc, cycle_now);
1006
1007 OWRITE(sc, OHCI_ITCTL(dmach),
1008 OHCI_CNTL_CYCMATCH_S | (cycle_match << 16) |
1009 OHCI_CNTL_DMA_RUN);
1010 #else
1011 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1012 #endif
1013 if (firewire_debug > 1) {
1014 printf("cycle_match: 0x%04x->0x%04x\n",
1015 cycle_now, cycle_match);
1016 dump_dma(sc, ITX_CH + dmach);
1017 dump_db(sc, ITX_CH + dmach);
1018 }
1019 } else if ((stat & OHCI_CNTL_CYCMATCH_S) == 0) {
1020 aprint_error_dev(fc->dev, "IT DMA underrun (0x%08x)\n", stat);
1021 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_WAKE);
1022 }
1023 out:
1024 return err;
1025 }
1026
1027 static int
1028 fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1029 {
1030 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1031
1032 OWRITE(sc, OHCI_ITCTLCLR(dmach),
1033 OHCI_CNTL_DMA_RUN | OHCI_CNTL_CYCMATCH_S);
1034 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1035 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1036 /* XXX we cannot free buffers until the DMA really stops */
1037 kpause("fwitxd", true, hz, NULL);
1038 fwohci_db_free(sc, &sc->it[dmach]);
1039 sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1040 return 0;
1041 }
1042
1043 static void
1044 fwohci_timeout(struct firewire_comm *fc)
1045 {
1046 #if 0
1047 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1048 #endif
1049 /* nothing? */
1050 }
1051
1052 #if BYTE_ORDER == BIG_ENDIAN
1053 static void
1054 fwohci_irx_post (struct firewire_comm *fc, uint32_t *qld)
1055 {
1056
1057 qld[0] = FWOHCI_DMA_READ(qld[0]);
1058 return;
1059 }
1060 #endif
1061
1062 static void
1063 fwohci_set_intr(struct firewire_comm *fc, int enable)
1064 {
1065 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1066
1067 if (firewire_debug)
1068 printf("fwohci_set_intr: %d\n", enable);
1069 if (enable) {
1070 sc->intmask |= OHCI_INT_EN;
1071 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
1072 } else {
1073 sc->intmask &= ~OHCI_INT_EN;
1074 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
1075 }
1076 }
1077
1078 /*
1079 * Communication with PHY device
1080 */
1081 /* XXX need lock for phy access */
1082 static uint32_t
1083 fwphy_rddata(struct fwohci_softc *sc, u_int addr)
1084 {
1085 uint32_t fun, stat;
1086 u_int i, retry = 0;
1087
1088 addr &= 0xf;
1089 #define MAX_RETRY 100
1090 again:
1091 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL);
1092 fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
1093 OWRITE(sc, OHCI_PHYACCESS, fun);
1094 for (i = 0; i < MAX_RETRY; i++) {
1095 fun = OREAD(sc, OHCI_PHYACCESS);
1096 if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
1097 break;
1098 DELAY(100);
1099 }
1100 if (i >= MAX_RETRY) {
1101 if (firewire_debug)
1102 printf("phy read failed(1).\n");
1103 if (++retry < MAX_RETRY) {
1104 DELAY(100);
1105 goto again;
1106 }
1107 }
1108 /* Make sure that SCLK is started */
1109 stat = OREAD(sc, FWOHCI_INTSTAT);
1110 if ((stat & OHCI_INT_REG_FAIL) != 0 ||
1111 ((fun >> PHYDEV_REGADDR) & 0xf) != addr) {
1112 if (firewire_debug)
1113 printf("phy read failed(2).\n");
1114 if (++retry < MAX_RETRY) {
1115 DELAY(100);
1116 goto again;
1117 }
1118 }
1119 if (firewire_debug || retry >= MAX_RETRY)
1120 aprint_error_dev(sc->fc.dev,
1121 "fwphy_rddata: 0x%x loop=%d, retry=%d\n",
1122 addr, i, retry);
1123 #undef MAX_RETRY
1124 return (fun >> PHYDEV_RDDATA) & 0xff;
1125 }
1126
1127 static uint32_t
1128 fwphy_wrdata(struct fwohci_softc *sc, uint32_t addr, uint32_t data)
1129 {
1130 uint32_t fun;
1131
1132 addr &= 0xf;
1133 data &= 0xff;
1134
1135 fun =
1136 (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA));
1137 OWRITE(sc, OHCI_PHYACCESS, fun);
1138 DELAY(100);
1139
1140 return fwphy_rddata(sc, addr);
1141 }
1142
1143 static int
1144 fwohci_probe_phy(struct fwohci_softc *sc)
1145 {
1146 uint32_t reg, reg2;
1147 int e1394a = 1;
1148
1149 /*
1150 * probe PHY parameters
1151 * 0. to prove PHY version, whether compliance of 1394a.
1152 * 1. to probe maximum speed supported by the PHY and
1153 * number of port supported by core-logic.
1154 * It is not actually available port on your PC .
1155 */
1156 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
1157 DELAY(500);
1158
1159 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
1160
1161 if ((reg >> 5) != 7) {
1162 sc->fc.mode &= ~FWPHYASYST;
1163 sc->fc.nport = reg & FW_PHY_NP;
1164 sc->fc.speed = reg & FW_PHY_SPD >> 6;
1165 if (sc->fc.speed > MAX_SPEED) {
1166 aprint_error_dev(sc->fc.dev,
1167 "invalid speed %d (fixed to %d).\n",
1168 sc->fc.speed, MAX_SPEED);
1169 sc->fc.speed = MAX_SPEED;
1170 }
1171 aprint_normal_dev(sc->fc.dev, "Phy 1394 only %s, %d ports.\n",
1172 fw_linkspeed[sc->fc.speed], sc->fc.nport);
1173 } else {
1174 reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
1175 sc->fc.mode |= FWPHYASYST;
1176 sc->fc.nport = reg & FW_PHY_NP;
1177 sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
1178 if (sc->fc.speed > MAX_SPEED) {
1179 aprint_error_dev(sc->fc.dev,
1180 "invalid speed %d (fixed to %d).\n",
1181 sc->fc.speed, MAX_SPEED);
1182 sc->fc.speed = MAX_SPEED;
1183 }
1184 aprint_normal_dev(sc->fc.dev,
1185 "Phy 1394a available %s, %d ports.\n",
1186 fw_linkspeed[sc->fc.speed], sc->fc.nport);
1187
1188 /* check programPhyEnable */
1189 reg2 = fwphy_rddata(sc, 5);
1190 #if 0
1191 if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
1192 #else /* XXX force to enable 1394a */
1193 if (e1394a) {
1194 #endif
1195 if (firewire_debug)
1196 printf("Enable 1394a Enhancements\n");
1197 /* enable EAA EMC */
1198 reg2 |= 0x03;
1199 /* set aPhyEnhanceEnable */
1200 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
1201 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
1202 }
1203 #if 0
1204 else {
1205 /* for safe */
1206 reg2 &= ~0x83;
1207 }
1208 #endif
1209 reg2 = fwphy_wrdata(sc, 5, reg2);
1210 }
1211
1212 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
1213 if ((reg >> 5) == 7) {
1214 reg = fwphy_rddata(sc, 4);
1215 reg |= 1 << 6;
1216 fwphy_wrdata(sc, 4, reg);
1217 reg = fwphy_rddata(sc, 4);
1218 }
1219 return 0;
1220 }
1221
1222 static void
1223 fwohci_reset(struct fwohci_softc *sc)
1224 {
1225 struct fwohcidb_tr *db_tr;
1226 uint32_t reg, reg2;
1227 int i, max_rec, speed;
1228
1229 /* Disable interrupts */
1230 OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
1231
1232 /* Now stopping all DMA channels */
1233 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1234 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1235 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1236 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1237
1238 OWRITE(sc, OHCI_IR_MASKCLR, ~0);
1239 for (i = 0; i < sc->fc.nisodma; i++) {
1240 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1241 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1242 }
1243
1244 /* FLUSH FIFO and reset Transmitter/Reciever */
1245 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1246 if (firewire_debug)
1247 printf("resetting OHCI...");
1248 i = 0;
1249 while (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
1250 if (i++ > 100)
1251 break;
1252 DELAY(1000);
1253 }
1254 if (firewire_debug)
1255 printf("done (loop=%d)\n", i);
1256
1257 /* Probe phy */
1258 fwohci_probe_phy(sc);
1259
1260 /* Probe link */
1261 reg = OREAD(sc, OHCI_BUS_OPT);
1262 reg2 = reg | OHCI_BUSFNC;
1263 max_rec = (reg & 0x0000f000) >> 12;
1264 speed = (reg & 0x00000007);
1265 aprint_normal_dev(sc->fc.dev, "Link %s, max_rec %d bytes.\n",
1266 fw_linkspeed[speed], MAXREC(max_rec));
1267 /* XXX fix max_rec */
1268 sc->fc.maxrec = sc->fc.speed + 8;
1269 if (max_rec != sc->fc.maxrec) {
1270 reg2 = (reg2 & 0xffff0fff) | (sc->fc.maxrec << 12);
1271 aprint_normal_dev(sc->fc.dev, "max_rec %d -> %d\n",
1272 MAXREC(max_rec), MAXREC(sc->fc.maxrec));
1273 }
1274 if (firewire_debug)
1275 printf("BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
1276 OWRITE(sc, OHCI_BUS_OPT, reg2);
1277
1278 /* Initialize registers */
1279 OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
1280 OWRITE(sc, OHCI_CROMPTR, sc->crom_dma.bus_addr);
1281 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
1282 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
1283 OWRITE(sc, OHCI_SID_BUF, sc->sid_dma.bus_addr);
1284 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
1285
1286 /* Enable link */
1287 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
1288
1289 /* Force to start async RX DMA */
1290 sc->arrq.xferq.flag &= ~FWXFERQ_RUNNING;
1291 sc->arrs.xferq.flag &= ~FWXFERQ_RUNNING;
1292 fwohci_rx_enable(sc, &sc->arrq);
1293 fwohci_rx_enable(sc, &sc->arrs);
1294
1295 /* Initialize async TX */
1296 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
1297 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
1298
1299 /* AT Retries */
1300 OWRITE(sc, FWOHCI_RETRY,
1301 /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */
1302 (0xffff << 16) | (0x0f << 8) | (0x0f << 4) | 0x0f);
1303
1304 sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq);
1305 sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq);
1306 sc->atrq.bottom = sc->atrq.top;
1307 sc->atrs.bottom = sc->atrs.top;
1308
1309 for (i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb;
1310 i++, db_tr = STAILQ_NEXT(db_tr, link))
1311 db_tr->xfer = NULL;
1312 for (i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb;
1313 i++, db_tr = STAILQ_NEXT(db_tr, link))
1314 db_tr->xfer = NULL;
1315
1316
1317 /* Enable interrupts */
1318 sc->intmask = (OHCI_INT_ERR | OHCI_INT_PHY_SID
1319 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1320 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1321 | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
1322 sc->intmask |= OHCI_INT_DMA_IR | OHCI_INT_DMA_IT;
1323 sc->intmask |= OHCI_INT_CYC_LOST | OHCI_INT_PHY_INT;
1324 OWRITE(sc, FWOHCI_INTMASK, sc->intmask);
1325 fwohci_set_intr(&sc->fc, 1);
1326 }
1327
1328 #define LAST_DB(dbtr) \
1329 &dbtr->db[(dbtr->dbcnt > 2) ? (dbtr->dbcnt - 1) : 0];
1330
1331 static void
1332 fwohci_execute_db(struct fwohcidb_tr *db_tr, bus_dmamap_t dmamap)
1333 {
1334 struct fwohcidb *db;
1335 bus_dma_segment_t *s;
1336 int i;
1337
1338 db = &db_tr->db[db_tr->dbcnt];
1339 for (i = 0; i < dmamap->dm_nsegs; i++) {
1340 s = &dmamap->dm_segs[i];
1341 FWOHCI_DMA_WRITE(db->db.desc.addr, s->ds_addr);
1342 FWOHCI_DMA_WRITE(db->db.desc.cmd, s->ds_len);
1343 FWOHCI_DMA_WRITE(db->db.desc.res, 0);
1344 db++;
1345 db_tr->dbcnt++;
1346 }
1347 }
1348
1349 static void
1350 fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1351 {
1352 struct fw_xfer *xfer;
1353 struct fw_pkt *fp;
1354 struct fwohci_txpkthdr *ohcifp;
1355 struct fwohcidb_tr *db_tr, *kick;
1356 struct fwohcidb *db;
1357 uint32_t *ld;
1358 int tcode, hdr_len, pl_off, fsegment = -1, i;
1359 const struct tcode_info *info;
1360 static int maxdesc = 0;
1361
1362 KASSERT(mutex_owned(&dbch->xferq.q_mtx));
1363
1364 #if DIAGNOSTIC
1365 if (dbch->off != OHCI_ATQOFF &&
1366 dbch->off != OHCI_ATSOFF)
1367 panic("not async tx");
1368 #endif
1369
1370 if (dbch->flags & FWOHCI_DBCH_FULL)
1371 return;
1372
1373 db_tr = dbch->top;
1374 kick = db_tr;
1375 if (dbch->pdb_tr != NULL) {
1376 kick = dbch->pdb_tr;
1377 fwdma_sync_multiseg(dbch->am, kick->idx, kick->idx,
1378 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1379 }
1380 txloop:
1381 xfer = STAILQ_FIRST(&dbch->xferq.q);
1382 if (xfer == NULL)
1383 goto kick;
1384 #if 0
1385 if (dbch->xferq.queued == 0)
1386 aprint_error_dev(sc->fc.dev, "TX queue empty\n");
1387 #endif
1388 STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
1389 db_tr->xfer = xfer;
1390 xfer->flag = FWXF_START;
1391
1392 fp = &xfer->send.hdr;
1393 tcode = fp->mode.common.tcode;
1394
1395 ohcifp = (struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
1396 info = &tinfo[tcode];
1397 hdr_len = pl_off = info->hdr_len;
1398
1399 ld = ohcifp->mode.ld;
1400 ld[0] = ld[1] = ld[2] = ld[3] = 0;
1401 for (i = 0; i < pl_off / 4; i++)
1402 ld[i] = fp->mode.ld[i];
1403
1404 ohcifp->mode.common.spd = xfer->send.spd & 0x7;
1405 if (tcode == FWTCODE_STREAM) {
1406 hdr_len = 8;
1407 ohcifp->mode.stream.len = fp->mode.stream.len;
1408 } else if (tcode == FWTCODE_PHY) {
1409 hdr_len = 12;
1410 ld[1] = fp->mode.ld[1];
1411 ld[2] = fp->mode.ld[2];
1412 ohcifp->mode.common.spd = 0;
1413 ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
1414 } else {
1415 ohcifp->mode.asycomm.dst = fp->mode.hdr.dst;
1416 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
1417 ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
1418 }
1419 db = db_tr->db;
1420 FWOHCI_DMA_WRITE(db->db.desc.cmd,
1421 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len);
1422 FWOHCI_DMA_WRITE(db->db.desc.addr, 0);
1423 FWOHCI_DMA_WRITE(db->db.desc.res, 0);
1424 /* Specify bound timer of asy. responce */
1425 if (dbch->off != OHCI_ATSOFF)
1426 FWOHCI_DMA_WRITE(db->db.desc.res,
1427 (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13));
1428 #if BYTE_ORDER == BIG_ENDIAN
1429 if (tcode == FWTCODE_WREQQ || tcode == FWTCODE_RRESQ)
1430 hdr_len = 12;
1431 for (i = 0; i < hdr_len / 4; i++)
1432 FWOHCI_DMA_WRITE(ld[i], ld[i]);
1433 #endif
1434
1435 again:
1436 db_tr->dbcnt = 2;
1437 db = &db_tr->db[db_tr->dbcnt];
1438 if (xfer->send.pay_len > 0) {
1439 int err;
1440 /* handle payload */
1441 if (xfer->mbuf == NULL)
1442 err = bus_dmamap_load(sc->fc.dmat, db_tr->dma_map,
1443 xfer->send.payload, xfer->send.pay_len, NULL,
1444 BUS_DMA_WAITOK);
1445 else {
1446 /* XXX we can handle only 6 (=8-2) mbuf chains */
1447 err = bus_dmamap_load_mbuf(sc->fc.dmat, db_tr->dma_map,
1448 xfer->mbuf, BUS_DMA_WAITOK);
1449 if (err == EFBIG) {
1450 struct mbuf *m0;
1451
1452 if (firewire_debug)
1453 printf("EFBIG.\n");
1454 m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1455 if (m0 != NULL) {
1456 m_copydata(xfer->mbuf, 0,
1457 xfer->mbuf->m_pkthdr.len,
1458 mtod(m0, void *));
1459 m0->m_len = m0->m_pkthdr.len =
1460 xfer->mbuf->m_pkthdr.len;
1461 m_freem(xfer->mbuf);
1462 xfer->mbuf = m0;
1463 goto again;
1464 }
1465 aprint_error_dev(sc->fc.dev,
1466 "m_getcl failed.\n");
1467 }
1468 }
1469 if (!err)
1470 fwohci_execute_db(db_tr, db_tr->dma_map);
1471 else
1472 aprint_error_dev(sc->fc.dev,
1473 "dmamap_load: err=%d\n", err);
1474 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
1475 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
1476 #if 0 /* OHCI_OUTPUT_MODE == 0 */
1477 for (i = 2; i < db_tr->dbcnt; i++)
1478 FWOHCI_DMA_SET(db_tr->db[i].db.desc.cmd,
1479 OHCI_OUTPUT_MORE);
1480 #endif
1481 }
1482 if (maxdesc < db_tr->dbcnt) {
1483 maxdesc = db_tr->dbcnt;
1484 if (firewire_debug)
1485 printf("maxdesc: %d\n", maxdesc);
1486 }
1487 /* last db */
1488 db = LAST_DB(db_tr);
1489 FWOHCI_DMA_SET(db->db.desc.cmd,
1490 OHCI_OUTPUT_LAST | OHCI_INTERRUPT_ALWAYS | OHCI_BRANCH_ALWAYS);
1491 FWOHCI_DMA_WRITE(db->db.desc.depend,
1492 STAILQ_NEXT(db_tr, link)->bus_addr);
1493
1494 if (fsegment == -1)
1495 fsegment = db_tr->dbcnt;
1496 if (dbch->pdb_tr != NULL) {
1497 db = LAST_DB(dbch->pdb_tr);
1498 FWOHCI_DMA_SET(db->db.desc.depend, db_tr->dbcnt);
1499 }
1500 dbch->xferq.queued++;
1501 dbch->pdb_tr = db_tr;
1502 db_tr = STAILQ_NEXT(db_tr, link);
1503 if (db_tr != dbch->bottom)
1504 goto txloop;
1505 else {
1506 aprint_error_dev(sc->fc.dev, "fwohci_start: lack of db_trq\n");
1507 dbch->flags |= FWOHCI_DBCH_FULL;
1508 }
1509 kick:
1510 /* kick asy q */
1511 fwdma_sync_multiseg(dbch->am, kick->idx, dbch->pdb_tr->idx,
1512 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1513
1514 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1515 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_WAKE);
1516 else {
1517 if (firewire_debug)
1518 printf("start AT DMA status=%x\n",
1519 OREAD(sc, OHCI_DMACTL(dbch->off)));
1520 OWRITE(sc, OHCI_DMACMD(dbch->off),
1521 dbch->top->bus_addr | fsegment);
1522 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN);
1523 dbch->xferq.flag |= FWXFERQ_RUNNING;
1524 }
1525
1526 dbch->top = db_tr;
1527 return;
1528 }
1529
1530 static void
1531 fwohci_start_atq(struct firewire_comm *fc)
1532 {
1533 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1534 struct fwohci_dbch *dbch = &sc->atrq;
1535
1536 mutex_enter(&dbch->xferq.q_mtx);
1537 fwohci_start(sc, dbch);
1538 mutex_exit(&dbch->xferq.q_mtx);
1539 return;
1540 }
1541
1542 static void
1543 fwohci_start_ats(struct firewire_comm *fc)
1544 {
1545 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1546 struct fwohci_dbch *dbch = &sc->atrs;
1547
1548 mutex_enter(&dbch->xferq.q_mtx);
1549 fwohci_start(sc, dbch);
1550 mutex_exit(&dbch->xferq.q_mtx);
1551 return;
1552 }
1553
1554 static void
1555 fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1556 {
1557 struct firewire_comm *fc = &sc->fc;
1558 struct fwohcidb_tr *tr;
1559 struct fwohcidb *db;
1560 struct fw_xfer *xfer;
1561 u_int stat, status;
1562 int packets = 0, ch, err = 0;
1563
1564 #if DIAGNOSTIC
1565 if (dbch->off != OHCI_ATQOFF &&
1566 dbch->off != OHCI_ATSOFF)
1567 panic("not async tx");
1568 #endif
1569 if (dbch->off == OHCI_ATQOFF)
1570 ch = ATRQ_CH;
1571 else /* OHCI_ATSOFF */
1572 ch = ATRS_CH;
1573
1574 mutex_enter(&dbch->xferq.q_mtx);
1575 tr = dbch->bottom;
1576 while (dbch->xferq.queued > 0) {
1577 fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx,
1578 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1579 db = LAST_DB(tr);
1580 status = FWOHCI_DMA_READ(db->db.desc.res) >> OHCI_STATUS_SHIFT;
1581 if (!(status & OHCI_CNTL_DMA_ACTIVE))
1582 if (fc->status != FWBUSINIT)
1583 goto out;
1584 if (tr->xfer->send.pay_len > 0) {
1585 bus_dmamap_sync(fc->dmat, tr->dma_map,
1586 0, tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1587 bus_dmamap_unload(fc->dmat, tr->dma_map);
1588 }
1589 #if 1
1590 if (firewire_debug > 1)
1591 dump_db(sc, ch);
1592 #endif
1593 if (status & OHCI_CNTL_DMA_DEAD) {
1594 /* Stop DMA */
1595 OWRITE(sc, OHCI_DMACTLCLR(dbch->off),
1596 OHCI_CNTL_DMA_RUN);
1597 aprint_error_dev(fc->dev, "force reset AT FIFO\n");
1598 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
1599 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
1600 OWRITE(sc, OHCI_DMACTLCLR(dbch->off),
1601 OHCI_CNTL_DMA_RUN);
1602 }
1603 stat = status & FWOHCIEV_MASK;
1604 switch(stat) {
1605 case FWOHCIEV_ACKPEND:
1606
1607 /* FALLTHROUGH */
1608
1609 case FWOHCIEV_ACKCOMPL:
1610 err = 0;
1611 break;
1612
1613 case FWOHCIEV_ACKBSA:
1614 case FWOHCIEV_ACKBSB:
1615 case FWOHCIEV_ACKBSX:
1616 aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat,
1617 fwohcicode[stat]);
1618 err = EBUSY;
1619 break;
1620
1621 case FWOHCIEV_FLUSHED:
1622 case FWOHCIEV_ACKTARD:
1623 aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat,
1624 fwohcicode[stat]);
1625 err = EAGAIN;
1626 break;
1627
1628 case FWOHCIEV_MISSACK:
1629 case FWOHCIEV_UNDRRUN:
1630 case FWOHCIEV_OVRRUN:
1631 case FWOHCIEV_DESCERR:
1632 case FWOHCIEV_DTRDERR:
1633 case FWOHCIEV_TIMEOUT:
1634 case FWOHCIEV_TCODERR:
1635 case FWOHCIEV_UNKNOWN:
1636 case FWOHCIEV_ACKDERR:
1637 case FWOHCIEV_ACKTERR:
1638 default:
1639 aprint_error_dev(fc->dev, "txd err=%2x %s\n", stat,
1640 fwohcicode[stat]);
1641 err = EINVAL;
1642 break;
1643 }
1644 dbch->xferq.queued--;
1645 dbch->bottom = STAILQ_NEXT(tr, link);
1646 if (tr->xfer != NULL) {
1647 xfer = tr->xfer;
1648 tr->xfer = NULL;
1649 mutex_exit(&dbch->xferq.q_mtx);
1650 if (xfer->flag & FWXF_RCVD) {
1651 #if 0
1652 if (firewire_debug)
1653 printf("already rcvd\n");
1654 #endif
1655 fw_xfer_done(xfer);
1656 } else {
1657 microtime(&xfer->tv);
1658 xfer->flag = FWXF_SENT;
1659 if (err == EBUSY) {
1660 xfer->flag = FWXF_BUSY;
1661 xfer->resp = err;
1662 xfer->recv.pay_len = 0;
1663 fw_xfer_done(xfer);
1664 } else if (stat != FWOHCIEV_ACKPEND) {
1665 if (stat != FWOHCIEV_ACKCOMPL)
1666 xfer->flag = FWXF_SENTERR;
1667 xfer->resp = err;
1668 xfer->recv.pay_len = 0;
1669 fw_xfer_done(xfer);
1670 }
1671 }
1672 mutex_enter(&dbch->xferq.q_mtx);
1673 /*
1674 * The watchdog timer takes care of split
1675 * transcation timeout for ACKPEND case.
1676 */
1677 } else
1678 aprint_error_dev(fc->dev, "this shouldn't happen\n");
1679 packets++;
1680 if (dbch->bottom == dbch->top) {
1681 /* we reaches the end of context program */
1682 if (firewire_debug && dbch->xferq.queued > 0)
1683 printf("queued > 0\n");
1684 break;
1685 }
1686 tr = dbch->bottom;
1687 }
1688 out:
1689 if (dbch->xferq.queued > 0 || packets > 0)
1690 fwdma_sync_multiseg(dbch->am, tr->idx, tr->idx,
1691 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1692 if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
1693 aprint_normal_dev(fc->dev, "make free slot\n");
1694 dbch->flags &= ~FWOHCI_DBCH_FULL;
1695 fwohci_start(sc, dbch);
1696 }
1697 mutex_exit(&dbch->xferq.q_mtx);
1698 }
1699
1700 static void
1701 fwohci_db_free(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1702 {
1703 struct fwohcidb_tr *db_tr, *last;
1704
1705 if ((dbch->flags & FWOHCI_DBCH_INIT) == 0)
1706 return;
1707
1708 for (last = db_tr = STAILQ_FIRST(&dbch->db_trq); db_tr != last;
1709 db_tr = STAILQ_NEXT(db_tr, link)) {
1710 bus_dmamap_destroy(sc->fc.dmat, db_tr->dma_map);
1711 if ((dbch->xferq.flag & FWXFERQ_EXTBUF) == 0 &&
1712 db_tr->buf != NULL) {
1713 fwdma_free(sc->fc.dmat, db_tr->dma_map, db_tr->buf);
1714 db_tr->buf = NULL;
1715 }
1716 }
1717 dbch->ndb = 0;
1718 db_tr = STAILQ_FIRST(&dbch->db_trq);
1719 fwdma_free_multiseg(dbch->am);
1720 free(db_tr, M_FW);
1721 STAILQ_INIT(&dbch->db_trq);
1722 dbch->flags &= ~FWOHCI_DBCH_INIT;
1723 seldestroy(&dbch->xferq.rsel);
1724 }
1725
1726 static void
1727 fwohci_db_init(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1728 {
1729 struct firewire_comm *fc = &sc->fc;
1730 struct fwohcidb_tr *db_tr, *lastq, *tmpq;
1731 int idb;
1732 const int db_tr_sz = sizeof(struct fwohcidb_tr) * dbch->ndb;
1733
1734 if ((dbch->flags & FWOHCI_DBCH_INIT) != 0)
1735 goto out;
1736
1737 /* allocate DB entries and attach one to each DMA channels */
1738 /* DB entry must start at 16 bytes bounary. */
1739 STAILQ_INIT(&dbch->db_trq);
1740 db_tr = (struct fwohcidb_tr *)malloc(db_tr_sz, M_FW, M_WAITOK | M_ZERO);
1741 if (db_tr == NULL) {
1742 aprint_error_dev(fc->dev, "malloc(1) failed\n");
1743 return;
1744 }
1745
1746 #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1747 dbch->am = fwdma_malloc_multiseg(fc, DB_SIZE(dbch), DB_SIZE(dbch),
1748 #if 0
1749 dbch->ndb, BUS_DMA_WAITOK);
1750 #else /* Ooops, debugging now... */
1751 dbch->ndb, BUS_DMA_WAITOK |
1752 (dbch->off == OHCI_ARQOFF || dbch->off == OHCI_ARSOFF) ?
1753 BUS_DMA_COHERENT : 0);
1754 #endif
1755 if (dbch->am == NULL) {
1756 aprint_error_dev(fc->dev, "fwdma_malloc_multiseg failed\n");
1757 free(db_tr, M_FW);
1758 return;
1759 }
1760 /* Attach DB to DMA ch. */
1761 for (idb = 0; idb < dbch->ndb; idb++) {
1762 db_tr->idx = idb;
1763 db_tr->dbcnt = 0;
1764 db_tr->db = (struct fwohcidb *)fwdma_v_addr(dbch->am, idb);
1765 db_tr->bus_addr = fwdma_bus_addr(dbch->am, idb);
1766 /* create dmamap for buffers */
1767 #define MAX_REQCOUNT 0xffff
1768 if (bus_dmamap_create(fc->dmat, dbch->xferq.psize,
1769 dbch->ndesc > 3 ? dbch->ndesc - 2 : 1, MAX_REQCOUNT, 0,
1770 0, &db_tr->dma_map) != 0) {
1771 aprint_error_dev(fc->dev, "bus_dmamap_create failed\n");
1772 dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1773 fwohci_db_free(sc, dbch);
1774 return;
1775 }
1776 if (dbch->off == OHCI_ARQOFF ||
1777 dbch->off == OHCI_ARSOFF) {
1778 db_tr->buf = fwdma_malloc(fc->dev, fc->dmat,
1779 &db_tr->dma_map, dbch->xferq.psize, 1,
1780 BUS_DMA_NOWAIT);
1781 if (db_tr->buf == NULL) {
1782 aprint_error_dev(fc->dev,
1783 "fwdma_malloc failed\n");
1784 dbch->flags = FWOHCI_DBCH_INIT; /* XXX fake */
1785 fwohci_db_free(sc, dbch);
1786 return;
1787 }
1788 }
1789 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1790 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1791 struct fw_bulkxfer *bulkxfer =
1792 &dbch->xferq.bulkxfer[idb / dbch->xferq.bnpacket];
1793
1794 if (idb % dbch->xferq.bnpacket == 0)
1795 bulkxfer->start = (void *)db_tr;
1796 if ((idb + 1) % dbch->xferq.bnpacket == 0)
1797 bulkxfer->end = (void *)db_tr;
1798 }
1799 db_tr++;
1800 }
1801 lastq = NULL;
1802 STAILQ_FOREACH(tmpq, &dbch->db_trq, link)
1803 lastq = tmpq;
1804 lastq->link.stqe_next = STAILQ_FIRST(&dbch->db_trq);
1805 out:
1806 dbch->xferq.queued = 0;
1807 dbch->pdb_tr = NULL;
1808 dbch->top = STAILQ_FIRST(&dbch->db_trq);
1809 dbch->bottom = dbch->top;
1810 dbch->flags = FWOHCI_DBCH_INIT;
1811 selinit(&dbch->xferq.rsel);
1812 }
1813
1814 static int
1815 fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1816 {
1817 int err = 0;
1818 int idb, z, i, dmach = 0, ldesc;
1819 struct fwohcidb_tr *db_tr;
1820 struct fwohcidb *db;
1821
1822 if (!(dbch->xferq.flag & FWXFERQ_EXTBUF)) {
1823 err = EINVAL;
1824 return err;
1825 }
1826 z = dbch->ndesc;
1827 for (dmach = 0; dmach < sc->fc.nisodma; dmach++)
1828 if (dbch->off == sc->it[dmach].off)
1829 break;
1830 if (dmach == sc->fc.nisodma) {
1831 err = EINVAL;
1832 return err;
1833 }
1834 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1835 return err;
1836 dbch->xferq.flag |= FWXFERQ_RUNNING;
1837 for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++)
1838 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1839 db_tr = dbch->top;
1840 for (idb = 0; idb < dbch->ndb; idb++) {
1841 fwohci_add_tx_buf(dbch, db_tr, idb);
1842 if (STAILQ_NEXT(db_tr, link) == NULL)
1843 break;
1844 db = db_tr->db;
1845 ldesc = db_tr->dbcnt - 1;
1846 FWOHCI_DMA_WRITE(db[0].db.desc.depend,
1847 STAILQ_NEXT(db_tr, link)->bus_addr | z);
1848 db[ldesc].db.desc.depend = db[0].db.desc.depend;
1849 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1850 if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1851 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1852 OHCI_INTERRUPT_ALWAYS);
1853 /* OHCI 1.1 and above */
1854 FWOHCI_DMA_SET(db[0].db.desc.cmd,
1855 OHCI_INTERRUPT_ALWAYS);
1856 }
1857 }
1858 db_tr = STAILQ_NEXT(db_tr, link);
1859 }
1860 FWOHCI_DMA_CLEAR(
1861 dbch->bottom->db[dbch->bottom->dbcnt - 1].db.desc.depend, 0xf);
1862 return err;
1863 }
1864
1865 static int
1866 fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1867 {
1868 struct fwohcidb_tr *db_tr;
1869 struct fwohcidb *db;
1870 int idb, z, i, ldesc, err = 0;
1871
1872 z = dbch->ndesc;
1873 if (dbch->xferq.flag & FWXFERQ_STREAM) {
1874 if (dbch->xferq.flag & FWXFERQ_RUNNING)
1875 return err;
1876 } else
1877 if (dbch->xferq.flag & FWXFERQ_RUNNING) {
1878 err = EBUSY;
1879 return err;
1880 }
1881 dbch->xferq.flag |= FWXFERQ_RUNNING;
1882 dbch->top = STAILQ_FIRST(&dbch->db_trq);
1883 for (i = 0, dbch->bottom = dbch->top; i < dbch->ndb - 1; i++)
1884 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1885 db_tr = dbch->top;
1886 if (db_tr->dbcnt != 0)
1887 goto run;
1888 for (idb = 0; idb < dbch->ndb; idb++) {
1889 if (dbch->off == OHCI_ARQOFF ||
1890 dbch->off == OHCI_ARSOFF)
1891 bus_dmamap_sync(sc->fc.dmat, db_tr->dma_map,
1892 0, db_tr->dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
1893 fwohci_add_rx_buf(dbch, db_tr, idb, &sc->dummy_dma);
1894 if (STAILQ_NEXT(db_tr, link) == NULL)
1895 break;
1896 db = db_tr->db;
1897 ldesc = db_tr->dbcnt - 1;
1898 FWOHCI_DMA_WRITE(db[ldesc].db.desc.depend,
1899 STAILQ_NEXT(db_tr, link)->bus_addr | z);
1900 if (dbch->xferq.flag & FWXFERQ_EXTBUF) {
1901 if (((idb + 1) % dbch->xferq.bnpacket) == 0) {
1902 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd,
1903 OHCI_INTERRUPT_ALWAYS);
1904 FWOHCI_DMA_CLEAR(db[ldesc].db.desc.depend, 0xf);
1905 }
1906 }
1907 db_tr = STAILQ_NEXT(db_tr, link);
1908 }
1909 FWOHCI_DMA_CLEAR(dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend,
1910 0xf);
1911 dbch->buf_offset = 0;
1912 run:
1913 fwdma_sync_multiseg_all(dbch->am,
1914 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1915 if (!(dbch->xferq.flag & FWXFERQ_STREAM)) {
1916 OWRITE(sc, OHCI_DMACMD(dbch->off), dbch->top->bus_addr | z);
1917 OWRITE(sc, OHCI_DMACTL(dbch->off), OHCI_CNTL_DMA_RUN);
1918 }
1919 return err;
1920 }
1921
1922 static int
1923 fwohci_next_cycle(struct fwohci_softc *sc, int cycle_now)
1924 {
1925 int sec, cycle, cycle_match;
1926
1927 cycle = cycle_now & 0x1fff;
1928 sec = cycle_now >> 13;
1929 #define CYCLE_MOD 0x10
1930 #if 1
1931 #define CYCLE_DELAY 8 /* min delay to start DMA */
1932 #else
1933 #define CYCLE_DELAY 7000 /* min delay to start DMA */
1934 #endif
1935 cycle = cycle + CYCLE_DELAY;
1936 if (cycle >= 8000) {
1937 sec++;
1938 cycle -= 8000;
1939 }
1940 cycle = roundup2(cycle, CYCLE_MOD);
1941 if (cycle >= 8000) {
1942 sec++;
1943 if (cycle == 8000)
1944 cycle = 0;
1945 else
1946 cycle = CYCLE_MOD;
1947 }
1948 cycle_match = ((sec << 13) | cycle) & 0x7ffff;
1949
1950 return cycle_match;
1951 }
1952
1953 #ifdef OHCI_DEBUG
1954 static void
1955 fwohci_dump_intr(struct fwohci_softc *sc, uint32_t stat)
1956 {
1957
1958 if (stat & OREAD(sc, FWOHCI_INTMASK))
1959 print("%s: INTERRUPT"
1960 " < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>"
1961 " 0x%08x, 0x%08x\n",
1962 device_xname(fc->dev),
1963 stat & OHCI_INT_EN ? "DMA_EN ":"",
1964 stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1965 stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1966 stat & OHCI_INT_ERR ? "INT_ERR ":"",
1967 stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1968 stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1969 stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1970 stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1971 stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1972 stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1973 stat & OHCI_INT_PHY_SID ? "SID ":"",
1974 stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1975 stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1976 stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1977 stat & OHCI_INT_DMA_IT ? "DMA_IT " :"",
1978 stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"",
1979 stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"",
1980 stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"",
1981 stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"",
1982 stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"",
1983 stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"",
1984 stat, OREAD(sc, FWOHCI_INTMASK)
1985 );
1986 }
1987 #endif
1988
1989 static void
1990 fwohci_intr_core(struct fwohci_softc *sc, uint32_t stat)
1991 {
1992 struct firewire_comm *fc = &sc->fc;
1993 uint32_t node_id, plen;
1994
1995 if ((stat & OHCI_INT_PHY_BUS_R) && (fc->status != FWBUSRESET)) {
1996 fc->status = FWBUSRESET;
1997 /* Disable bus reset interrupt until sid recv. */
1998 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
1999
2000 aprint_normal_dev(fc->dev, "BUS reset\n");
2001 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
2002 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
2003
2004 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
2005 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
2006 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
2007 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
2008
2009 fw_busreset(&sc->fc, FWBUSRESET);
2010 OWRITE(sc, OHCI_CROMHDR, ntohl(sc->fc.config_rom[0]));
2011 OWRITE(sc, OHCI_BUS_OPT, ntohl(sc->fc.config_rom[2]));
2012 }
2013 if (stat & OHCI_INT_PHY_SID) {
2014 /* Enable bus reset interrupt */
2015 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
2016 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
2017
2018 /* Allow async. request to us */
2019 OWRITE(sc, OHCI_AREQHI, 1 << 31);
2020 if (firewire_phydma_enable) {
2021 /* allow from all nodes */
2022 OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
2023 OWRITE(sc, OHCI_PREQLO, 0xffffffff);
2024 /* 0 to 4GB region */
2025 OWRITE(sc, OHCI_PREQUPPER, 0x10000);
2026 }
2027 /* Set ATRetries register */
2028 OWRITE(sc, OHCI_ATRETRY, 1<<(13+16) | 0xfff);
2029
2030 /*
2031 * Checking whether the node is root or not. If root, turn on
2032 * cycle master.
2033 */
2034 node_id = OREAD(sc, FWOHCI_NODEID);
2035 plen = OREAD(sc, OHCI_SID_CNT);
2036
2037 fc->nodeid = node_id & 0x3f;
2038 aprint_normal_dev(fc->dev, "node_id=0x%08x, gen=%d, ",
2039 node_id, (plen >> 16) & 0xff);
2040 if (!(node_id & OHCI_NODE_VALID)) {
2041 aprint_error_dev(fc->dev, "Bus reset failure\n");
2042 goto sidout;
2043 }
2044
2045 /* cycle timer */
2046 sc->cycle_lost = 0;
2047 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_CYC_LOST);
2048 if ((node_id & OHCI_NODE_ROOT) && !nocyclemaster) {
2049 aprint_normal("CYCLEMASTER mode\n");
2050 OWRITE(sc, OHCI_LNKCTL,
2051 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
2052 } else {
2053 aprint_normal("non CYCLEMASTER mode\n");
2054 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
2055 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
2056 }
2057
2058 fc->status = FWBUSINIT;
2059
2060 fwohci_task_sid(sc);
2061 }
2062 sidout:
2063 if ((stat & ~(OHCI_INT_PHY_BUS_R | OHCI_INT_PHY_SID)))
2064 fwohci_task_dma(sc);
2065 }
2066
2067 static void
2068 fwohci_intr_dma(struct fwohci_softc *sc, uint32_t stat)
2069 {
2070 struct firewire_comm *fc = &sc->fc;
2071 uint32_t irstat, itstat;
2072 u_int i;
2073
2074 if (stat & OHCI_INT_DMA_IR) {
2075 irstat = atomic_swap_32(&sc->irstat, 0);
2076 for (i = 0; i < fc->nisodma; i++)
2077 if ((irstat & (1 << i)) != 0) {
2078 struct fwohci_dbch *dbch = &sc->ir[i];
2079
2080 if ((dbch->xferq.flag & FWXFERQ_OPEN) == 0) {
2081 aprint_error_dev(fc->dev,
2082 "dma(%d) not active\n", i);
2083 continue;
2084 }
2085 fwohci_rbuf_update(sc, i);
2086 }
2087 }
2088 if (stat & OHCI_INT_DMA_IT) {
2089 itstat = atomic_swap_32(&sc->itstat, 0);
2090 for (i = 0; i < fc->nisodma; i++)
2091 if ((itstat & (1 << i)) != 0)
2092 fwohci_tbuf_update(sc, i);
2093 }
2094 if (stat & OHCI_INT_DMA_PRRS) {
2095 #if 0
2096 dump_dma(sc, ARRS_CH);
2097 dump_db(sc, ARRS_CH);
2098 #endif
2099 fwohci_arcv(sc, &sc->arrs);
2100 }
2101 if (stat & OHCI_INT_DMA_PRRQ) {
2102 #if 0
2103 dump_dma(sc, ARRQ_CH);
2104 dump_db(sc, ARRQ_CH);
2105 #endif
2106 fwohci_arcv(sc, &sc->arrq);
2107 }
2108 if (stat & OHCI_INT_CYC_LOST) {
2109 if (sc->cycle_lost >= 0)
2110 sc->cycle_lost++;
2111 if (sc->cycle_lost > 10) {
2112 sc->cycle_lost = -1;
2113 #if 0
2114 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCTIMER);
2115 #endif
2116 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
2117 aprint_error_dev(fc->dev, "too many cycle lost, "
2118 "no cycle master present?\n");
2119 }
2120 }
2121 if (stat & OHCI_INT_DMA_ATRQ)
2122 fwohci_txd(sc, &(sc->atrq));
2123 if (stat & OHCI_INT_DMA_ATRS)
2124 fwohci_txd(sc, &(sc->atrs));
2125 if (stat & OHCI_INT_PW_ERR)
2126 aprint_error_dev(fc->dev, "posted write error\n");
2127 if (stat & OHCI_INT_ERR)
2128 aprint_error_dev(fc->dev, "unrecoverable error\n");
2129 if (stat & OHCI_INT_PHY_INT)
2130 aprint_normal_dev(fc->dev, "phy int\n");
2131
2132 return;
2133 }
2134
2135 static void
2136 fwohci_task_sid(struct fwohci_softc *sc)
2137 {
2138 struct firewire_comm *fc = &sc->fc;
2139 uint32_t *buf;
2140 int i, plen;
2141
2142 plen = OREAD(sc, OHCI_SID_CNT);
2143
2144 if (plen & OHCI_SID_ERR) {
2145 aprint_error_dev(fc->dev, "SID Error\n");
2146 return;
2147 }
2148 plen &= OHCI_SID_CNT_MASK;
2149 if (plen < 4 || plen > OHCI_SIDSIZE) {
2150 aprint_error_dev(fc->dev, "invalid SID len = %d\n", plen);
2151 return;
2152 }
2153 plen -= 4; /* chop control info */
2154 buf = (uint32_t *)malloc(OHCI_SIDSIZE, M_FW, M_NOWAIT);
2155 if (buf == NULL) {
2156 aprint_error_dev(fc->dev, "malloc failed\n");
2157 return;
2158 }
2159 for (i = 0; i < plen / 4; i++)
2160 buf[i] = FWOHCI_DMA_READ(sc->sid_buf[i + 1]);
2161 #if 1 /* XXX needed?? */
2162 /* pending all pre-bus_reset packets */
2163 fwohci_txd(sc, &sc->atrq);
2164 fwohci_txd(sc, &sc->atrs);
2165 fwohci_arcv(sc, &sc->arrs);
2166 fwohci_arcv(sc, &sc->arrq);
2167 fw_drain_txq(fc);
2168 #endif
2169 fw_sidrcv(fc, buf, plen);
2170 free(buf, M_FW);
2171 }
2172
2173 static void
2174 fwohci_task_dma(struct fwohci_softc *sc)
2175 {
2176 uint32_t stat;
2177
2178 again:
2179 stat = atomic_swap_32(&sc->intstat, 0);
2180 if (stat)
2181 fwohci_intr_dma(sc, stat);
2182 else
2183 return;
2184 goto again;
2185 }
2186
2187 static void
2188 fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
2189 {
2190 struct firewire_comm *fc = &sc->fc;
2191 struct fwohcidb *db;
2192 struct fw_bulkxfer *chunk;
2193 struct fw_xferq *it;
2194 uint32_t stat;
2195 #if 0
2196 uint32_t count;
2197 #endif
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 #if 0
2213 count =
2214 FWOHCI_DMA_READ(db[ldesc].db.desc.res) & OHCI_COUNT_MASK;
2215 #else
2216 (void)FWOHCI_DMA_READ(db[ldesc].db.desc.res);
2217 #endif
2218 if (stat == 0)
2219 break;
2220 STAILQ_REMOVE_HEAD(&it->stdma, link);
2221 switch (stat & FWOHCIEV_MASK) {
2222 case FWOHCIEV_ACKCOMPL:
2223 #if 0
2224 printf("0x%08x\n", count);
2225 #endif
2226 break;
2227 default:
2228 aprint_error_dev(fc->dev,
2229 "Isochronous transmit err %02x(%s)\n",
2230 stat, fwohcicode[stat & 0x1f]);
2231 }
2232 STAILQ_INSERT_TAIL(&it->stfree, chunk, link);
2233 w++;
2234 }
2235 mutex_exit(&fc->fc_mtx);
2236 if (w)
2237 wakeup(it);
2238 }
2239
2240 static void
2241 fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
2242 {
2243 struct firewire_comm *fc = &sc->fc;
2244 struct fwohcidb_tr *db_tr;
2245 struct fw_bulkxfer *chunk;
2246 struct fw_xferq *ir;
2247 uint32_t stat;
2248 int w = 0, ldesc;
2249
2250 ir = fc->ir[dmach];
2251 ldesc = sc->ir[dmach].ndesc - 1;
2252
2253 #if 0
2254 dump_db(sc, dmach);
2255 #endif
2256 if ((ir->flag & FWXFERQ_HANDLER) == 0)
2257 mutex_enter(&fc->fc_mtx);
2258 fwdma_sync_multiseg_all(sc->ir[dmach].am, BUS_DMASYNC_POSTREAD);
2259 while ((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
2260 db_tr = (struct fwohcidb_tr *)chunk->end;
2261 stat = FWOHCI_DMA_READ(db_tr->db[ldesc].db.desc.res) >>
2262 OHCI_STATUS_SHIFT;
2263 if (stat == 0)
2264 break;
2265
2266 if (chunk->mbuf != NULL) {
2267 bus_dmamap_sync(fc->dmat, db_tr->dma_map, 0,
2268 db_tr->dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
2269 bus_dmamap_unload(fc->dmat, db_tr->dma_map);
2270 } else if (ir->buf != NULL)
2271 fwdma_sync_multiseg(ir->buf, chunk->poffset,
2272 ir->bnpacket, BUS_DMASYNC_POSTREAD);
2273 else
2274 /* XXX */
2275 aprint_error_dev(fc->dev,
2276 "fwohci_rbuf_update: this shouldn't happend\n");
2277
2278 STAILQ_REMOVE_HEAD(&ir->stdma, link);
2279 STAILQ_INSERT_TAIL(&ir->stvalid, chunk, link);
2280 switch (stat & FWOHCIEV_MASK) {
2281 case FWOHCIEV_ACKCOMPL:
2282 chunk->resp = 0;
2283 break;
2284 default:
2285 chunk->resp = EINVAL;
2286 aprint_error_dev(fc->dev,
2287 "Isochronous receive err %02x(%s)\n",
2288 stat, fwohcicode[stat & 0x1f]);
2289 }
2290 w++;
2291 }
2292 if ((ir->flag & FWXFERQ_HANDLER) == 0)
2293 mutex_exit(&fc->fc_mtx);
2294 if (w == 0)
2295 return;
2296 if (ir->flag & FWXFERQ_HANDLER)
2297 ir->hand(ir);
2298 else
2299 wakeup(ir);
2300 }
2301
2302 static void
2303 dump_dma(struct fwohci_softc *sc, uint32_t ch)
2304 {
2305 struct fwohci_dbch *dbch;
2306 uint32_t cntl, stat, cmd, match;
2307
2308 if (ch == ATRQ_CH)
2309 dbch = &sc->atrq;
2310 else if (ch == ATRS_CH)
2311 dbch = &sc->atrs;
2312 else if (ch == ARRQ_CH)
2313 dbch = &sc->arrq;
2314 else if (ch == ARRS_CH)
2315 dbch = &sc->arrs;
2316 else if (ch < IRX_CH)
2317 dbch = &sc->it[ch - ITX_CH];
2318 else
2319 dbch = &sc->ir[ch - IRX_CH];
2320 cntl = stat = OREAD(sc, dbch->off);
2321 cmd = OREAD(sc, dbch->off + 0xc);
2322 match = OREAD(sc, dbch->off + 0x10);
2323
2324 aprint_normal_dev(sc->fc.dev,
2325 "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2326 ch,
2327 cntl,
2328 cmd,
2329 match);
2330 stat &= 0xffff;
2331 if (stat)
2332 aprint_normal_dev(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2333 ch,
2334 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2335 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2336 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2337 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2338 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2339 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2340 fwohcicode[stat & 0x1f],
2341 stat & 0x1f
2342 );
2343 else
2344 aprint_normal_dev(sc->fc.dev, "dma %d ch: Nostat\n", ch);
2345 }
2346
2347 static void
2348 dump_db(struct fwohci_softc *sc, uint32_t ch)
2349 {
2350 struct fwohci_dbch *dbch;
2351 struct fwohcidb_tr *cp = NULL, *pp;
2352 struct fwohcidb *curr = NULL;
2353 #if 0
2354 struct fwohcidb_tr *np = NULL;
2355 struct fwohcidb *prev, *next = NULL;
2356 #endif
2357 int idb, jdb;
2358 uint32_t cmd;
2359
2360 if (ch == ATRQ_CH)
2361 dbch = &sc->atrq;
2362 else if (ch == ATRS_CH)
2363 dbch = &sc->atrs;
2364 else if (ch == ARRQ_CH)
2365 dbch = &sc->arrq;
2366 else if (ch == ARRS_CH)
2367 dbch = &sc->arrs;
2368 else if (ch < IRX_CH)
2369 dbch = &sc->it[ch - ITX_CH];
2370 else
2371 dbch = &sc->ir[ch - IRX_CH];
2372 cmd = OREAD(sc, dbch->off + 0xc);
2373
2374 if (dbch->ndb == 0) {
2375 aprint_error_dev(sc->fc.dev, "No DB is attached ch=%d\n", ch);
2376 return;
2377 }
2378 pp = dbch->top;
2379 #if 0
2380 prev = pp->db;
2381 #endif
2382 for (idb = 0; idb < dbch->ndb; idb++) {
2383 cp = STAILQ_NEXT(pp, link);
2384 if (cp == NULL) {
2385 curr = NULL;
2386 goto outdb;
2387 }
2388 #if 0
2389 np = STAILQ_NEXT(cp, link);
2390 #endif
2391 for (jdb = 0; jdb < dbch->ndesc; jdb++)
2392 if ((cmd & 0xfffffff0) == cp->bus_addr) {
2393 curr = cp->db;
2394 #if 0
2395 if (np != NULL)
2396 next = np->db;
2397 else
2398 next = NULL;
2399 #endif
2400 goto outdb;
2401 }
2402 pp = STAILQ_NEXT(pp, link);
2403 if (pp == NULL) {
2404 curr = NULL;
2405 goto outdb;
2406 }
2407 #if 0
2408 prev = pp->db;
2409 #endif
2410 }
2411 outdb:
2412 if (curr != NULL) {
2413 #if 0
2414 aprint_normal("Prev DB %d\n", ch);
2415 print_db(pp, prev, ch, dbch->ndesc);
2416 #endif
2417 aprint_normal("Current DB %d\n", ch);
2418 print_db(cp, curr, ch, dbch->ndesc);
2419 #if 0
2420 aprint_normal("Next DB %d\n", ch);
2421 print_db(np, next, ch, dbch->ndesc);
2422 #endif
2423 } else
2424 aprint_error("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
2425 return;
2426 }
2427
2428 static void
2429 print_db(struct fwohcidb_tr *db_tr, struct fwohcidb *db, uint32_t ch,
2430 uint32_t hogemax)
2431 {
2432 fwohcireg_t stat;
2433 int i, key;
2434 uint32_t cmd, res;
2435
2436 if (db == NULL) {
2437 aprint_error("No Descriptor is found\n");
2438 return;
2439 }
2440
2441 aprint_normal("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2442 ch,
2443 "Current",
2444 "OP ",
2445 "KEY",
2446 "INT",
2447 "BR ",
2448 "len",
2449 "Addr",
2450 "Depend",
2451 "Stat",
2452 "Cnt");
2453 for (i = 0; i <= hogemax; i++) {
2454 cmd = FWOHCI_DMA_READ(db[i].db.desc.cmd);
2455 res = FWOHCI_DMA_READ(db[i].db.desc.res);
2456 key = cmd & OHCI_KEY_MASK;
2457 stat = res >> OHCI_STATUS_SHIFT;
2458 aprint_normal("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2459 (uintmax_t)db_tr->bus_addr,
2460 dbcode[(cmd >> 28) & 0xf],
2461 dbkey[(cmd >> 24) & 0x7],
2462 dbcond[(cmd >> 20) & 0x3],
2463 dbcond[(cmd >> 18) & 0x3],
2464 cmd & OHCI_COUNT_MASK,
2465 FWOHCI_DMA_READ(db[i].db.desc.addr),
2466 FWOHCI_DMA_READ(db[i].db.desc.depend),
2467 stat,
2468 res & OHCI_COUNT_MASK);
2469 if (stat & 0xff00)
2470 aprint_normal(" %s%s%s%s%s%s %s(%x)\n",
2471 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
2472 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
2473 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
2474 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
2475 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
2476 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
2477 fwohcicode[stat & 0x1f],
2478 stat & 0x1f
2479 );
2480 else
2481 aprint_normal(" Nostat\n");
2482 if (key == OHCI_KEY_ST2)
2483 aprint_normal("0x%08x 0x%08x 0x%08x 0x%08x\n",
2484 FWOHCI_DMA_READ(db[i+1].db.immed[0]),
2485 FWOHCI_DMA_READ(db[i+1].db.immed[1]),
2486 FWOHCI_DMA_READ(db[i+1].db.immed[2]),
2487 FWOHCI_DMA_READ(db[i+1].db.immed[3]));
2488 if (key == OHCI_KEY_DEVICE)
2489 return;
2490 if ((cmd & OHCI_BRANCH_MASK) == OHCI_BRANCH_ALWAYS)
2491 return;
2492 if ((cmd & OHCI_CMD_MASK) == OHCI_OUTPUT_LAST)
2493 return;
2494 if ((cmd & OHCI_CMD_MASK) == OHCI_INPUT_LAST)
2495 return;
2496 if (key == OHCI_KEY_ST2)
2497 i++;
2498 }
2499 return;
2500 }
2501
2502 static void
2503 fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2504 {
2505 struct fwohcidb_tr *db_tr /*, *fdb_tr */;
2506 struct fwohci_dbch *dbch;
2507 struct fwohcidb *db;
2508 struct fw_pkt *fp;
2509 struct fwohci_txpkthdr *ohcifp;
2510 unsigned short chtag;
2511 int idb;
2512
2513 KASSERT(mutex_owner(&sc->fc.fc_mtx));
2514
2515 dbch = &sc->it[dmach];
2516 chtag = sc->it[dmach].xferq.flag & 0xff;
2517
2518 db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2519 /*
2520 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2521 aprint_normal(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2522 */
2523 for (idb = 0; idb < dbch->xferq.bnpacket; idb++) {
2524 db = db_tr->db;
2525 fp = (struct fw_pkt *)db_tr->buf;
2526 ohcifp = (struct fwohci_txpkthdr *) db[1].db.immed;
2527 ohcifp->mode.ld[0] = fp->mode.ld[0];
2528 ohcifp->mode.common.spd = 0 & 0x7;
2529 ohcifp->mode.stream.len = fp->mode.stream.len;
2530 ohcifp->mode.stream.chtag = chtag;
2531 ohcifp->mode.stream.tcode = 0xa;
2532 #if BYTE_ORDER == BIG_ENDIAN
2533 FWOHCI_DMA_WRITE(db[1].db.immed[0], db[1].db.immed[0]);
2534 FWOHCI_DMA_WRITE(db[1].db.immed[1], db[1].db.immed[1]);
2535 #endif
2536
2537 FWOHCI_DMA_CLEAR(db[2].db.desc.cmd, OHCI_COUNT_MASK);
2538 FWOHCI_DMA_SET(db[2].db.desc.cmd, fp->mode.stream.len);
2539 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2540 #if 0 /* if bulkxfer->npackets changes */
2541 db[2].db.desc.cmd =
2542 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS;
2543 db[0].db.desc.depend = db[dbch->ndesc - 1].db.desc.depend =
2544 STAILQ_NEXT(db_tr, link)->bus_addr | dbch->ndesc;
2545 #else
2546 FWOHCI_DMA_SET(db[0].db.desc.depend, dbch->ndesc);
2547 FWOHCI_DMA_SET(db[dbch->ndesc - 1].db.desc.depend, dbch->ndesc);
2548 #endif
2549 bulkxfer->end = (void *)db_tr;
2550 db_tr = STAILQ_NEXT(db_tr, link);
2551 }
2552 db = ((struct fwohcidb_tr *)bulkxfer->end)->db;
2553 FWOHCI_DMA_CLEAR(db[0].db.desc.depend, 0xf);
2554 FWOHCI_DMA_CLEAR(db[dbch->ndesc - 1].db.desc.depend, 0xf);
2555 #if 0 /* if bulkxfer->npackets changes */
2556 db[dbch->ndesc - 1].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2557 /* OHCI 1.1 and above */
2558 db[0].db.desc.control |= OHCI_INTERRUPT_ALWAYS;
2559 #endif
2560 /*
2561 db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2562 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2563 aprint_normal(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2564 */
2565 return;
2566 }
2567
2568 static int
2569 fwohci_add_tx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2570 int poffset)
2571 {
2572 struct fwohcidb *db = db_tr->db;
2573 struct fw_xferq *it;
2574 int err = 0;
2575
2576 it = &dbch->xferq;
2577 if (it->buf == 0) {
2578 err = EINVAL;
2579 return err;
2580 }
2581 db_tr->buf = fwdma_v_addr(it->buf, poffset);
2582 db_tr->dbcnt = 3;
2583
2584 FWOHCI_DMA_WRITE(db[0].db.desc.cmd,
2585 OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8);
2586 FWOHCI_DMA_WRITE(db[0].db.desc.addr, 0);
2587 memset((void *)db[1].db.immed, 0, sizeof(db[1].db.immed));
2588 FWOHCI_DMA_WRITE(db[2].db.desc.addr,
2589 fwdma_bus_addr(it->buf, poffset) + sizeof(uint32_t));
2590
2591 FWOHCI_DMA_WRITE(db[2].db.desc.cmd,
2592 OHCI_OUTPUT_LAST | OHCI_UPDATE | OHCI_BRANCH_ALWAYS);
2593 #if 1
2594 FWOHCI_DMA_WRITE(db[0].db.desc.res, 0);
2595 FWOHCI_DMA_WRITE(db[2].db.desc.res, 0);
2596 #endif
2597 return 0;
2598 }
2599
2600 int
2601 fwohci_add_rx_buf(struct fwohci_dbch *dbch, struct fwohcidb_tr *db_tr,
2602 int poffset, struct fwdma_alloc *dummy_dma)
2603 {
2604 struct fwohcidb *db = db_tr->db;
2605 struct fw_xferq *rq;
2606 int i, ldesc;
2607 bus_addr_t dbuf[2];
2608 int dsiz[2];
2609
2610 rq = &dbch->xferq;
2611 if (rq->buf == NULL && (dbch->xferq.flag & FWXFERQ_EXTBUF) == 0) {
2612 /* async */
2613 db_tr->dbcnt = 1;
2614 dsiz[0] = rq->psize;
2615 dbuf[0] = db_tr->dma_map->dm_segs[0].ds_addr;
2616 } else {
2617 /* isoc */
2618 db_tr->dbcnt = 0;
2619 dsiz[db_tr->dbcnt] = sizeof(uint32_t);
2620 dbuf[db_tr->dbcnt++] = dummy_dma->bus_addr;
2621 dsiz[db_tr->dbcnt] = rq->psize;
2622 if (rq->buf != NULL) {
2623 db_tr->buf = fwdma_v_addr(rq->buf, poffset);
2624 dbuf[db_tr->dbcnt] = fwdma_bus_addr(rq->buf, poffset);
2625 }
2626 db_tr->dbcnt++;
2627 }
2628 for (i = 0; i < db_tr->dbcnt; i++) {
2629 FWOHCI_DMA_WRITE(db[i].db.desc.addr, dbuf[i]);
2630 FWOHCI_DMA_WRITE(db[i].db.desc.cmd, OHCI_INPUT_MORE | dsiz[i]);
2631 if (rq->flag & FWXFERQ_STREAM)
2632 FWOHCI_DMA_SET(db[i].db.desc.cmd, OHCI_UPDATE);
2633 FWOHCI_DMA_WRITE(db[i].db.desc.res, dsiz[i]);
2634 }
2635 ldesc = db_tr->dbcnt - 1;
2636 if (rq->flag & FWXFERQ_STREAM)
2637 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_INPUT_LAST);
2638 FWOHCI_DMA_SET(db[ldesc].db.desc.cmd, OHCI_BRANCH_ALWAYS);
2639 return 0;
2640 }
2641
2642
2643 static int
2644 fwohci_arcv_swap(struct fw_pkt *fp, int len)
2645 {
2646 struct fw_pkt *fp0;
2647 uint32_t ld0;
2648 int slen, hlen;
2649 #if BYTE_ORDER == BIG_ENDIAN
2650 int i;
2651 #endif
2652
2653 ld0 = FWOHCI_DMA_READ(fp->mode.ld[0]);
2654 #if 0
2655 printf("ld0: x%08x\n", ld0);
2656 #endif
2657 fp0 = (struct fw_pkt *)&ld0;
2658 /* determine length to swap */
2659 switch (fp0->mode.common.tcode) {
2660 case FWTCODE_WRES:
2661 case FWTCODE_RREQQ:
2662 case FWTCODE_WREQQ:
2663 case FWTCODE_RRESQ:
2664 case FWOHCITCODE_PHY:
2665 slen = 12;
2666 break;
2667
2668 case FWTCODE_RREQB:
2669 case FWTCODE_WREQB:
2670 case FWTCODE_LREQ:
2671 case FWTCODE_RRESB:
2672 case FWTCODE_LRES:
2673 slen = 16;
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