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