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