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