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