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