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