1 /* $NetBSD: fwohci.c,v 1.119 2009/03/18 17:06:49 cegger Exp $ */
4 * Copyright (c) 2003 Hidetoshi Shimokawa
5 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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:
19 * This product includes software developed by K. Kobayashi and H. Shimokawa
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.
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.
36 * $FreeBSD: src/sys/dev/firewire/fwohci.c,v 1.93 2007/06/08 09:04:30 simokawa Exp $
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.119 2009/03/18 17:06:49 cegger Exp $");
49 #if defined(__FreeBSD__)
50 #include <sys/param.h>
51 #include <sys/systm.h>
53 #include <sys/malloc.h>
54 #include <sys/sockio.h>
55 #include <sys/sysctl.h>
57 #include <sys/kernel.h>
59 #include <sys/endian.h>
62 #include <machine/bus.h>
64 #if defined(__DragonFly__) || __FreeBSD_version < 500000
65 #include <machine/clock.h> /* for DELAY() */
71 #include "firewirereg.h"
73 #include "fwohcireg.h"
74 #include "fwohcivar.h"
75 #include "firewire_phy.h"
77 #include <dev/firewire/fw_port.h>
78 #include <dev/firewire/firewire.h>
79 #include <dev/firewire/firewirereg.h>
80 #include <dev/firewire/fwdma.h>
81 #include <dev/firewire/fwohcireg.h>
82 #include <dev/firewire/fwohcivar.h>
83 #include <dev/firewire/firewire_phy.h>
85 #elif defined(__NetBSD__)
86 #include <sys/param.h>
87 #include <sys/device.h>
88 #include <sys/errno.h>
90 #include <sys/kernel.h>
91 #include <sys/malloc.h>
94 #include <sys/reboot.h>
95 #include <sys/sysctl.h>
96 #include <sys/systm.h>
100 #include <dev/ieee1394/fw_port.h>
101 #include <dev/ieee1394/firewire.h>
102 #include <dev/ieee1394/firewirereg.h>
103 #include <dev/ieee1394/fwdma.h>
104 #include <dev/ieee1394/fwohcireg.h>
105 #include <dev/ieee1394/fwohcivar.h>
106 #include <dev/ieee1394/firewire_phy.h>
113 static int nocyclemaster
= 0;
114 int firewire_phydma_enable
= 1;
115 #if defined(__FreeBSD__)
116 SYSCTL_DECL(_hw_firewire
);
117 SYSCTL_INT(_hw_firewire
, OID_AUTO
, nocyclemaster
, CTLFLAG_RW
, &nocyclemaster
, 0,
118 "Do not send cycle start packets");
119 SYSCTL_INT(_hw_firewire
, OID_AUTO
, phydma_enable
, CTLFLAG_RW
,
120 &firewire_phydma_enable
, 1, "Allow physical request DMA from firewire");
121 TUNABLE_INT("hw.firewire.phydma_enable", &firewire_phydma_enable
);
122 #elif defined(__NetBSD__)
124 * Setup sysctl(3) MIB, hw.fwohci.*
126 * TBD condition CTLFLAG_PERMANENT on being a module or not
128 SYSCTL_SETUP(sysctl_fwohci
, "sysctl fwohci(4) subtree setup")
130 int rc
, fwohci_node_num
;
131 const struct sysctlnode
*node
;
133 if ((rc
= sysctl_createv(clog
, 0, NULL
, NULL
,
134 CTLFLAG_PERMANENT
, CTLTYPE_NODE
, "hw", NULL
,
135 NULL
, 0, NULL
, 0, CTL_HW
, CTL_EOL
)) != 0) {
139 if ((rc
= sysctl_createv(clog
, 0, NULL
, &node
,
140 CTLFLAG_PERMANENT
, CTLTYPE_NODE
, "fwohci",
141 SYSCTL_DESCR("fwohci controls"),
142 NULL
, 0, NULL
, 0, CTL_HW
, CTL_CREATE
, CTL_EOL
)) != 0) {
145 fwohci_node_num
= node
->sysctl_num
;
147 /* fwohci no cyclemaster flag */
148 if ((rc
= sysctl_createv(clog
, 0, NULL
, &node
,
149 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
, CTLTYPE_INT
,
150 "nocyclemaster", SYSCTL_DESCR("Do not send cycle start packets"),
151 NULL
, 0, &nocyclemaster
,
152 0, CTL_HW
, fwohci_node_num
, CTL_CREATE
, CTL_EOL
)) != 0) {
156 /* fwohci physical request DMA enable */
157 if ((rc
= sysctl_createv(clog
, 0, NULL
, &node
,
158 CTLFLAG_PERMANENT
| CTLFLAG_READWRITE
, CTLTYPE_INT
, "phydma_enable",
159 SYSCTL_DESCR("Allow physical request DMA from firewire"),
160 NULL
, 0, &firewire_phydma_enable
,
161 0, CTL_HW
, fwohci_node_num
, CTL_CREATE
, CTL_EOL
)) != 0) {
167 printf("%s: sysctl_createv failed (rc = %d)\n", __func__
, rc
);
171 static const char * const dbcode
[16] = {"OUTM", "OUTL","INPM","INPL",
172 "STOR","LOAD","NOP ","STOP",
173 "", "", "", "", "", "", "", ""};
175 static const char * const dbkey
[8] = {"ST0", "ST1","ST2","ST3",
176 "UNDEF","REG","SYS","DEV"};
177 static const char * const dbcond
[4] = {"NEV","C=1", "C=0", "ALL"};
178 static const char * const fwohcicode
[32] = {
179 "No stat","Undef","long","miss Ack err",
180 "FIFO underrun","FIFO overrun","desc err", "data read err",
181 "data write err","bus reset","timeout","tcode err",
182 "Undef","Undef","unknown event","flushed",
183 "Undef","ack complete","ack pend","Undef",
184 "ack busy_X","ack busy_A","ack busy_B","Undef",
185 "Undef","Undef","Undef","ack tardy",
186 "Undef","ack data_err","ack type_err",""};
189 extern const char *fw_linkspeed
[];
190 static uint32_t const tagbit
[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31};
192 static const struct tcode_info tinfo
[] = {
193 /* hdr_len block flag valid_response*/
194 /* 0 WREQQ */ {16, FWTI_REQ
| FWTI_TLABEL
, FWTCODE_WRES
},
195 /* 1 WREQB */ {16, FWTI_REQ
| FWTI_TLABEL
| FWTI_BLOCK_ASY
, FWTCODE_WRES
},
196 /* 2 WRES */ {12, FWTI_RES
, 0xff},
197 /* 3 XXX */ { 0, 0, 0xff},
198 /* 4 RREQQ */ {12, FWTI_REQ
| FWTI_TLABEL
, FWTCODE_RRESQ
},
199 /* 5 RREQB */ {16, FWTI_REQ
| FWTI_TLABEL
, FWTCODE_RRESB
},
200 /* 6 RRESQ */ {16, FWTI_RES
, 0xff},
201 /* 7 RRESB */ {16, FWTI_RES
| FWTI_BLOCK_ASY
, 0xff},
202 /* 8 CYCS */ { 0, 0, 0xff},
203 /* 9 LREQ */ {16, FWTI_REQ
| FWTI_TLABEL
| FWTI_BLOCK_ASY
, FWTCODE_LRES
},
204 /* a STREAM */ { 4, FWTI_REQ
| FWTI_BLOCK_STR
, 0xff},
205 /* b LRES */ {16, FWTI_RES
| FWTI_BLOCK_ASY
, 0xff},
206 /* c XXX */ { 0, 0, 0xff},
207 /* d XXX */ { 0, 0, 0xff},
208 /* e PHY */ {12, FWTI_REQ
, 0xff},
209 /* f XXX */ { 0, 0, 0xff}
212 #define OHCI_WRITE_SIGMASK 0xffff0000
213 #define OHCI_READ_SIGMASK 0xffff0000
215 #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
216 #define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r))
218 static void fwohci_ibr (struct firewire_comm
*);
219 static void fwohci_db_init (struct fwohci_softc
*, struct fwohci_dbch
*);
220 static void fwohci_db_free (struct fwohci_dbch
*);
221 static void fwohci_arcv (struct fwohci_softc
*, struct fwohci_dbch
*, int);
222 static void fwohci_txd (struct fwohci_softc
*, struct fwohci_dbch
*);
223 static void fwohci_start_atq (struct firewire_comm
*);
224 static void fwohci_start_ats (struct firewire_comm
*);
225 static void fwohci_start (struct fwohci_softc
*, struct fwohci_dbch
*);
226 static uint32_t fwphy_wrdata ( struct fwohci_softc
*, uint32_t, uint32_t);
227 static uint32_t fwphy_rddata ( struct fwohci_softc
*, uint32_t);
228 static int fwohci_rx_enable (struct fwohci_softc
*, struct fwohci_dbch
*);
229 static int fwohci_tx_enable (struct fwohci_softc
*, struct fwohci_dbch
*);
230 static int fwohci_irx_enable (struct firewire_comm
*, int);
231 static int fwohci_irx_disable (struct firewire_comm
*, int);
232 #if BYTE_ORDER == BIG_ENDIAN
233 static void fwohci_irx_post (struct firewire_comm
*, uint32_t *);
235 static int fwohci_itxbuf_enable (struct firewire_comm
*, int);
236 static int fwohci_itx_disable (struct firewire_comm
*, int);
237 static void fwohci_timeout (void *);
238 static void fwohci_set_intr (struct firewire_comm
*, int);
240 static int fwohci_add_rx_buf (struct fwohci_dbch
*, struct fwohcidb_tr
*, int, struct fwdma_alloc
*);
241 static int fwohci_add_tx_buf (struct fwohci_dbch
*, struct fwohcidb_tr
*, int);
242 static void dump_db (struct fwohci_softc
*, uint32_t);
243 static void print_db (struct fwohcidb_tr
*, struct fwohcidb
*, uint32_t , uint32_t);
244 static void dump_dma (struct fwohci_softc
*, uint32_t);
245 static uint32_t fwohci_cyctimer (struct firewire_comm
*);
246 static void fwohci_rbuf_update (struct fwohci_softc
*, int);
247 static void fwohci_tbuf_update (struct fwohci_softc
*, int);
248 void fwohci_txbufdb (struct fwohci_softc
*, int , struct fw_bulkxfer
*);
249 static void fwohci_task_busreset(void *, int);
250 static void fwohci_task_sid(void *, int);
251 static void fwohci_task_dma(void *, int);
252 #if defined(__NetBSD__)
253 int fwohci_print(void *, const char *);
257 * memory allocated for DMA programs
259 #define DMA_PROG_ALLOC (8 * PAGE_SIZE)
261 #define NDB FWMAXQUEUE
263 #define OHCI_VERSION 0x00
264 #define OHCI_ATRETRY 0x08
265 #define OHCI_CROMHDR 0x18
266 #define OHCI_BUS_OPT 0x20
267 #define OHCI_BUSIRMC (1 << 31)
268 #define OHCI_BUSCMC (1 << 30)
269 #define OHCI_BUSISC (1 << 29)
270 #define OHCI_BUSBMC (1 << 28)
271 #define OHCI_BUSPMC (1 << 27)
272 #define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\
273 OHCI_BUSBMC | OHCI_BUSPMC
275 #define OHCI_EUID_HI 0x24
276 #define OHCI_EUID_LO 0x28
278 #define OHCI_CROMPTR 0x34
279 #define OHCI_HCCCTL 0x50
280 #define OHCI_HCCCTLCLR 0x54
281 #define OHCI_AREQHI 0x100
282 #define OHCI_AREQHICLR 0x104
283 #define OHCI_AREQLO 0x108
284 #define OHCI_AREQLOCLR 0x10c
285 #define OHCI_PREQHI 0x110
286 #define OHCI_PREQHICLR 0x114
287 #define OHCI_PREQLO 0x118
288 #define OHCI_PREQLOCLR 0x11c
289 #define OHCI_PREQUPPER 0x120
291 #define OHCI_SID_BUF 0x64
292 #define OHCI_SID_CNT 0x68
293 #define OHCI_SID_ERR (1 << 31)
294 #define OHCI_SID_CNT_MASK 0xffc
296 #define OHCI_IT_STAT 0x90
297 #define OHCI_IT_STATCLR 0x94
298 #define OHCI_IT_MASK 0x98
299 #define OHCI_IT_MASKCLR 0x9c
301 #define OHCI_IR_STAT 0xa0
302 #define OHCI_IR_STATCLR 0xa4
303 #define OHCI_IR_MASK 0xa8
304 #define OHCI_IR_MASKCLR 0xac
306 #define OHCI_LNKCTL 0xe0
307 #define OHCI_LNKCTLCLR 0xe4
309 #define OHCI_PHYACCESS 0xec
310 #define OHCI_CYCLETIMER 0xf0
312 #define OHCI_DMACTL(off) (off)
313 #define OHCI_DMACTLCLR(off) (off + 4)
314 #define OHCI_DMACMD(off) (off + 0xc)
315 #define OHCI_DMAMATCH(off) (off + 0x10)
317 #define OHCI_ATQOFF 0x180
318 #define OHCI_ATQCTL OHCI_ATQOFF
319 #define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4)
320 #define OHCI_ATQCMD (OHCI_ATQOFF + 0xc)
321 #define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10)
323 #define OHCI_ATSOFF 0x1a0
324 #define OHCI_ATSCTL OHCI_ATSOFF
325 #define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4)
326 #define OHCI_ATSCMD (OHCI_ATSOFF + 0xc)
327 #define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10)
329 #define OHCI_ARQOFF 0x1c0
330 #define OHCI_ARQCTL OHCI_ARQOFF
331 #define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4)
332 #define OHCI_ARQCMD (OHCI_ARQOFF + 0xc)
333 #define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10)
335 #define OHCI_ARSOFF 0x1e0
336 #define OHCI_ARSCTL OHCI_ARSOFF
337 #define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4)
338 #define OHCI_ARSCMD (OHCI_ARSOFF + 0xc)
339 #define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10)
341 #define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH))
342 #define OHCI_ITCTL(CH) (OHCI_ITOFF(CH))
343 #define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4)
344 #define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc)
346 #define OHCI_IROFF(CH) (0x400 + 0x20 * (CH))
347 #define OHCI_IRCTL(CH) (OHCI_IROFF(CH))
348 #define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4)
349 #define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc)
350 #define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10)
352 #if defined(__FreeBSD__)
353 d_ioctl_t fwohci_ioctl
;
354 #elif defined(__NetBSD__)
355 dev_type_ioctl(fwohci_ioctl
);
359 * Communication with PHY device
361 /* XXX need lock for phy access */
363 fwphy_wrdata( struct fwohci_softc
*sc
, uint32_t addr
, uint32_t data
)
370 fun
= (PHYDEV_WRCMD
| (addr
<< PHYDEV_REGADDR
) | (data
<< PHYDEV_WRDATA
));
371 OWRITE(sc
, OHCI_PHYACCESS
, fun
);
374 return(fwphy_rddata( sc
, addr
));
378 fwohci_set_bus_manager(struct firewire_comm
*fc
, u_int node
)
380 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
384 #define OHCI_CSR_DATA 0x0c
385 #define OHCI_CSR_COMP 0x10
386 #define OHCI_CSR_CONT 0x14
387 #define OHCI_BUS_MANAGER_ID 0
389 OWRITE(sc
, OHCI_CSR_DATA
, node
);
390 OWRITE(sc
, OHCI_CSR_COMP
, 0x3f);
391 OWRITE(sc
, OHCI_CSR_CONT
, OHCI_BUS_MANAGER_ID
);
392 for (i
= 0; !(OREAD(sc
, OHCI_CSR_CONT
) & (1<<31)) && (i
< 1000); i
++)
394 bm
= OREAD(sc
, OHCI_CSR_DATA
);
395 if((bm
& 0x3f) == 0x3f)
398 fw_printf(sc
->fc
.dev
,
399 "fw_set_bus_manager: %d->%d (loop=%d)\n", bm
, node
, i
);
405 fwphy_rddata(struct fwohci_softc
*sc
, u_int addr
)
411 #define MAX_RETRY 100
413 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_REG_FAIL
);
414 fun
= PHYDEV_RDCMD
| (addr
<< PHYDEV_REGADDR
);
415 OWRITE(sc
, OHCI_PHYACCESS
, fun
);
416 for ( i
= 0 ; i
< MAX_RETRY
; i
++ ){
417 fun
= OREAD(sc
, OHCI_PHYACCESS
);
418 if ((fun
& PHYDEV_RDCMD
) == 0 && (fun
& PHYDEV_RDDONE
) != 0)
424 fw_printf(sc
->fc
.dev
, "phy read failed(1).\n");
425 if (++retry
< MAX_RETRY
) {
430 /* Make sure that SCLK is started */
431 stat
= OREAD(sc
, FWOHCI_INTSTAT
);
432 if ((stat
& OHCI_INT_REG_FAIL
) != 0 ||
433 ((fun
>> PHYDEV_REGADDR
) & 0xf) != addr
) {
435 fw_printf(sc
->fc
.dev
, "phy read failed(2).\n");
436 if (++retry
< MAX_RETRY
) {
441 if (firewire_debug
|| retry
>= MAX_RETRY
)
442 fw_printf(sc
->fc
.dev
,
443 "fwphy_rddata: 0x%x loop=%d, retry=%d\n", addr
, i
, retry
);
445 return((fun
>> PHYDEV_RDDATA
)& 0xff);
447 /* Device specific ioctl. */
451 struct fwohci_softc
*fc
;
453 struct fw_reg_req_t
*reg
= (struct fw_reg_req_t
*) data
;
454 uint32_t *dmach
= (uint32_t *) data
;
459 fc
= (struct fwohci_softc
*)sc
->fc
;
466 #define OHCI_MAX_REG 0x800
467 if(reg
->addr
<= OHCI_MAX_REG
){
468 OWRITE(fc
, reg
->addr
, reg
->data
);
469 reg
->data
= OREAD(fc
, reg
->addr
);
475 if(reg
->addr
<= OHCI_MAX_REG
){
476 reg
->data
= OREAD(fc
, reg
->addr
);
481 /* Read DMA descriptors for debug */
483 if(*dmach
<= OHCI_MAX_DMA_CH
){
484 dump_dma(fc
, *dmach
);
490 /* Read/Write Phy registers */
491 #define OHCI_MAX_PHY_REG 0xf
492 case FWOHCI_RDPHYREG
:
493 if (reg
->addr
<= OHCI_MAX_PHY_REG
)
494 reg
->data
= fwphy_rddata(fc
, reg
->addr
);
498 case FWOHCI_WRPHYREG
:
499 if (reg
->addr
<= OHCI_MAX_PHY_REG
)
500 reg
->data
= fwphy_wrdata(fc
, reg
->addr
, reg
->data
);
512 fwohci_probe_phy(struct fwohci_softc
*sc
, device_t dev
)
517 * probe PHY parameters
518 * 0. to prove PHY version, whether compliance of 1394a.
519 * 1. to probe maximum speed supported by the PHY and
520 * number of port supported by core-logic.
521 * It is not actually available port on your PC .
523 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_LPS
);
526 reg
= fwphy_rddata(sc
, FW_PHY_SPD_REG
);
528 if((reg
>> 5) != 7 ){
529 sc
->fc
.mode
&= ~FWPHYASYST
;
530 sc
->fc
.nport
= reg
& FW_PHY_NP
;
531 sc
->fc
.speed
= reg
& FW_PHY_SPD
>> 6;
532 if (sc
->fc
.speed
> MAX_SPEED
) {
533 fw_printf(dev
, "invalid speed %d (fixed to %d).\n",
534 sc
->fc
.speed
, MAX_SPEED
);
535 sc
->fc
.speed
= MAX_SPEED
;
537 fw_printf(dev
, "Phy 1394 only %s, %d ports.\n",
538 fw_linkspeed
[sc
->fc
.speed
], sc
->fc
.nport
);
540 reg2
= fwphy_rddata(sc
, FW_PHY_ESPD_REG
);
541 sc
->fc
.mode
|= FWPHYASYST
;
542 sc
->fc
.nport
= reg
& FW_PHY_NP
;
543 sc
->fc
.speed
= (reg2
& FW_PHY_ESPD
) >> 5;
544 if (sc
->fc
.speed
> MAX_SPEED
) {
545 fw_printf(dev
, "invalid speed %d (fixed to %d).\n",
546 sc
->fc
.speed
, MAX_SPEED
);
547 sc
->fc
.speed
= MAX_SPEED
;
549 fw_printf(dev
, "Phy 1394a available %s, %d ports.\n",
550 fw_linkspeed
[sc
->fc
.speed
], sc
->fc
.nport
);
552 /* check programPhyEnable */
553 reg2
= fwphy_rddata(sc
, 5);
555 if (e1394a
&& (OREAD(sc
, OHCI_HCCCTL
) & OHCI_HCC_PRPHY
)) {
556 #else /* XXX force to enable 1394a */
560 fw_printf(dev
, "Enable 1394a Enhancements\n");
563 /* set aPhyEnhanceEnable */
564 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_PHYEN
);
565 OWRITE(sc
, OHCI_HCCCTLCLR
, OHCI_HCC_PRPHY
);
573 reg2
= fwphy_wrdata(sc
, 5, reg2
);
576 reg
= fwphy_rddata(sc
, FW_PHY_SPD_REG
);
577 if((reg
>> 5) == 7 ){
578 reg
= fwphy_rddata(sc
, 4);
580 fwphy_wrdata(sc
, 4, reg
);
581 reg
= fwphy_rddata(sc
, 4);
588 fwohci_reset(struct fwohci_softc
*sc
, device_t dev
)
590 int i
, max_rec
, speed
;
592 struct fwohcidb_tr
*db_tr
;
594 /* Disable interrupts */
595 OWRITE(sc
, FWOHCI_INTMASKCLR
, ~0);
597 /* Now stopping all DMA channels */
598 OWRITE(sc
, OHCI_ARQCTLCLR
, OHCI_CNTL_DMA_RUN
);
599 OWRITE(sc
, OHCI_ARSCTLCLR
, OHCI_CNTL_DMA_RUN
);
600 OWRITE(sc
, OHCI_ATQCTLCLR
, OHCI_CNTL_DMA_RUN
);
601 OWRITE(sc
, OHCI_ATSCTLCLR
, OHCI_CNTL_DMA_RUN
);
603 OWRITE(sc
, OHCI_IR_MASKCLR
, ~0);
604 for( i
= 0 ; i
< sc
->fc
.nisodma
; i
++ ){
605 OWRITE(sc
, OHCI_IRCTLCLR(i
), OHCI_CNTL_DMA_RUN
);
606 OWRITE(sc
, OHCI_ITCTLCLR(i
), OHCI_CNTL_DMA_RUN
);
609 /* FLUSH FIFO and reset Transmitter/Reciever */
610 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_RESET
);
612 fw_printf(dev
, "resetting OHCI...");
614 while(OREAD(sc
, OHCI_HCCCTL
) & OHCI_HCC_RESET
) {
615 if (i
++ > 100) break;
619 printf("done (loop=%d)\n", i
);
622 fwohci_probe_phy(sc
, dev
);
625 reg
= OREAD(sc
, OHCI_BUS_OPT
);
626 reg2
= reg
| OHCI_BUSFNC
;
627 max_rec
= (reg
& 0x0000f000) >> 12;
628 speed
= (reg
& 0x00000007);
629 fw_printf(dev
, "Link %s, max_rec %d bytes.\n",
630 fw_linkspeed
[speed
], MAXREC(max_rec
));
631 /* XXX fix max_rec */
632 sc
->fc
.maxrec
= sc
->fc
.speed
+ 8;
633 if (max_rec
!= sc
->fc
.maxrec
) {
634 reg2
= (reg2
& 0xffff0fff) | (sc
->fc
.maxrec
<< 12);
635 fw_printf(dev
, "max_rec %d -> %d\n",
636 MAXREC(max_rec
), MAXREC(sc
->fc
.maxrec
));
639 fw_printf(dev
, "BUS_OPT 0x%x -> 0x%x\n", reg
, reg2
);
640 OWRITE(sc
, OHCI_BUS_OPT
, reg2
);
642 /* Initialize registers */
643 OWRITE(sc
, OHCI_CROMHDR
, sc
->fc
.config_rom
[0]);
644 OWRITE(sc
, OHCI_CROMPTR
, sc
->crom_dma
.bus_addr
);
645 OWRITE(sc
, OHCI_HCCCTLCLR
, OHCI_HCC_BIGEND
);
646 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_POSTWR
);
647 OWRITE(sc
, OHCI_SID_BUF
, sc
->sid_dma
.bus_addr
);
648 OWRITE(sc
, OHCI_LNKCTL
, OHCI_CNTL_SID
);
651 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_LINKEN
);
653 /* Force to start async RX DMA */
654 sc
->arrq
.xferq
.flag
&= ~FWXFERQ_RUNNING
;
655 sc
->arrs
.xferq
.flag
&= ~FWXFERQ_RUNNING
;
656 fwohci_rx_enable(sc
, &sc
->arrq
);
657 fwohci_rx_enable(sc
, &sc
->arrs
);
659 /* Initialize async TX */
660 OWRITE(sc
, OHCI_ATQCTLCLR
, OHCI_CNTL_DMA_RUN
| OHCI_CNTL_DMA_DEAD
);
661 OWRITE(sc
, OHCI_ATSCTLCLR
, OHCI_CNTL_DMA_RUN
| OHCI_CNTL_DMA_DEAD
);
664 OWRITE(sc
, FWOHCI_RETRY
,
665 /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */
666 (0xffff << 16 ) | (0x0f << 8) | (0x0f << 4) | 0x0f) ;
668 sc
->atrq
.top
= STAILQ_FIRST(&sc
->atrq
.db_trq
);
669 sc
->atrs
.top
= STAILQ_FIRST(&sc
->atrs
.db_trq
);
670 sc
->atrq
.bottom
= sc
->atrq
.top
;
671 sc
->atrs
.bottom
= sc
->atrs
.top
;
673 for( i
= 0, db_tr
= sc
->atrq
.top
; i
< sc
->atrq
.ndb
;
674 i
++, db_tr
= STAILQ_NEXT(db_tr
, link
)){
677 for( i
= 0, db_tr
= sc
->atrs
.top
; i
< sc
->atrs
.ndb
;
678 i
++, db_tr
= STAILQ_NEXT(db_tr
, link
)){
683 /* Enable interrupts */
684 sc
->intmask
= (OHCI_INT_ERR
| OHCI_INT_PHY_SID
685 | OHCI_INT_DMA_ATRQ
| OHCI_INT_DMA_ATRS
686 | OHCI_INT_DMA_PRRQ
| OHCI_INT_DMA_PRRS
687 | OHCI_INT_PHY_BUS_R
| OHCI_INT_PW_ERR
);
688 sc
->intmask
|= OHCI_INT_DMA_IR
| OHCI_INT_DMA_IT
;
689 sc
->intmask
|= OHCI_INT_CYC_LOST
| OHCI_INT_PHY_INT
;
690 OWRITE(sc
, FWOHCI_INTMASK
, sc
->intmask
);
691 fwohci_set_intr(&sc
->fc
, 1);
695 fwohci_init(struct fwohci_softc
*sc
, device_t dev
)
702 reg
= OREAD(sc
, OHCI_VERSION
);
703 mver
= (reg
>> 16) & 0xff;
704 fw_printf(dev
, "OHCI version %x.%x (ROM=%d)\n",
705 mver
, reg
& 0xff, (reg
>>24) & 1);
706 if (mver
< 1 || mver
> 9) {
707 fw_printf(dev
, "invalid OHCI version\n");
711 /* Available Isochronous DMA channel probe */
712 OWRITE(sc
, OHCI_IT_MASK
, 0xffffffff);
713 OWRITE(sc
, OHCI_IR_MASK
, 0xffffffff);
714 reg
= OREAD(sc
, OHCI_IT_MASK
) & OREAD(sc
, OHCI_IR_MASK
);
715 OWRITE(sc
, OHCI_IT_MASKCLR
, 0xffffffff);
716 OWRITE(sc
, OHCI_IR_MASKCLR
, 0xffffffff);
717 for (i
= 0; i
< 0x20; i
++)
718 if ((reg
& (1 << i
)) == 0)
721 fw_printf(dev
, "No. of Isochronous channels is %d.\n", i
);
725 sc
->fc
.arq
= &sc
->arrq
.xferq
;
726 sc
->fc
.ars
= &sc
->arrs
.xferq
;
727 sc
->fc
.atq
= &sc
->atrq
.xferq
;
728 sc
->fc
.ats
= &sc
->atrs
.xferq
;
730 sc
->arrq
.xferq
.psize
= roundup2(FWPMAX_S400
, PAGE_SIZE
);
731 sc
->arrs
.xferq
.psize
= roundup2(FWPMAX_S400
, PAGE_SIZE
);
732 sc
->atrq
.xferq
.psize
= roundup2(FWPMAX_S400
, PAGE_SIZE
);
733 sc
->atrs
.xferq
.psize
= roundup2(FWPMAX_S400
, PAGE_SIZE
);
735 sc
->arrq
.xferq
.start
= NULL
;
736 sc
->arrs
.xferq
.start
= NULL
;
737 sc
->atrq
.xferq
.start
= fwohci_start_atq
;
738 sc
->atrs
.xferq
.start
= fwohci_start_ats
;
740 sc
->arrq
.xferq
.buf
= NULL
;
741 sc
->arrs
.xferq
.buf
= NULL
;
742 sc
->atrq
.xferq
.buf
= NULL
;
743 sc
->atrs
.xferq
.buf
= NULL
;
745 sc
->arrq
.xferq
.dmach
= -1;
746 sc
->arrs
.xferq
.dmach
= -1;
747 sc
->atrq
.xferq
.dmach
= -1;
748 sc
->atrs
.xferq
.dmach
= -1;
752 sc
->atrq
.ndesc
= 8; /* equal to maximum of mbuf chains */
756 sc
->arrs
.ndb
= NDB
/ 2;
758 sc
->atrs
.ndb
= NDB
/ 2;
760 for( i
= 0 ; i
< sc
->fc
.nisodma
; i
++ ){
761 sc
->fc
.it
[i
] = &sc
->it
[i
].xferq
;
762 sc
->fc
.ir
[i
] = &sc
->ir
[i
].xferq
;
763 sc
->it
[i
].xferq
.dmach
= i
;
764 sc
->ir
[i
].xferq
.dmach
= i
;
769 sc
->fc
.tcode
= tinfo
;
772 sc
->fc
.config_rom
= fwdma_malloc(&sc
->fc
, CROMSIZE
, CROMSIZE
,
773 &sc
->crom_dma
, BUS_DMA_WAITOK
);
774 if(sc
->fc
.config_rom
== NULL
){
775 fw_printf(dev
, "config_rom alloc failed.");
780 memset(&sc
->fc
.config_rom
[0], 0, CROMSIZE
);
781 sc
->fc
.config_rom
[1] = 0x31333934;
782 sc
->fc
.config_rom
[2] = 0xf000a002;
783 sc
->fc
.config_rom
[3] = OREAD(sc
, OHCI_EUID_HI
);
784 sc
->fc
.config_rom
[4] = OREAD(sc
, OHCI_EUID_LO
);
785 sc
->fc
.config_rom
[5] = 0;
786 sc
->fc
.config_rom
[0] = (4 << 24) | (5 << 16);
788 sc
->fc
.config_rom
[0] |= fw_crc16(&sc
->fc
.config_rom
[1], 5*4);
791 /* SID recieve buffer must align 2^11 */
792 #define OHCI_SIDSIZE (1 << 11)
793 sc
->sid_buf
= fwdma_malloc(&sc
->fc
, OHCI_SIDSIZE
, OHCI_SIDSIZE
,
794 &sc
->sid_dma
, BUS_DMA_WAITOK
);
795 if (sc
->sid_buf
== NULL
) {
796 fw_printf(dev
, "sid_buf alloc failed.");
800 fwdma_malloc(&sc
->fc
, sizeof(uint32_t), sizeof(uint32_t),
801 &sc
->dummy_dma
, BUS_DMA_WAITOK
);
803 if (sc
->dummy_dma
.v_addr
== NULL
) {
804 fw_printf(dev
, "dummy_dma alloc failed.");
808 fwohci_db_init(sc
, &sc
->arrq
);
809 if ((sc
->arrq
.flags
& FWOHCI_DBCH_INIT
) == 0)
812 fwohci_db_init(sc
, &sc
->arrs
);
813 if ((sc
->arrs
.flags
& FWOHCI_DBCH_INIT
) == 0)
816 fwohci_db_init(sc
, &sc
->atrq
);
817 if ((sc
->atrq
.flags
& FWOHCI_DBCH_INIT
) == 0)
820 fwohci_db_init(sc
, &sc
->atrs
);
821 if ((sc
->atrs
.flags
& FWOHCI_DBCH_INIT
) == 0)
824 sc
->fc
.eui
.hi
= OREAD(sc
, FWOHCIGUID_H
);
825 sc
->fc
.eui
.lo
= OREAD(sc
, FWOHCIGUID_L
);
826 for( i
= 0 ; i
< 8 ; i
++)
827 ui
[i
] = FW_EUI64_BYTE(&sc
->fc
.eui
,i
);
828 fw_printf(dev
, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
829 ui
[0], ui
[1], ui
[2], ui
[3], ui
[4], ui
[5], ui
[6], ui
[7]);
831 sc
->fc
.ioctl
= fwohci_ioctl
;
832 sc
->fc
.cyctimer
= fwohci_cyctimer
;
833 sc
->fc
.set_bmr
= fwohci_set_bus_manager
;
834 sc
->fc
.ibr
= fwohci_ibr
;
835 sc
->fc
.irx_enable
= fwohci_irx_enable
;
836 sc
->fc
.irx_disable
= fwohci_irx_disable
;
838 sc
->fc
.itx_enable
= fwohci_itxbuf_enable
;
839 sc
->fc
.itx_disable
= fwohci_itx_disable
;
840 #if BYTE_ORDER == BIG_ENDIAN
841 sc
->fc
.irx_post
= fwohci_irx_post
;
843 sc
->fc
.irx_post
= NULL
;
845 sc
->fc
.itx_post
= NULL
;
846 sc
->fc
.timeout
= fwohci_timeout
;
847 sc
->fc
.poll
= fwohci_poll
;
848 sc
->fc
.set_intr
= fwohci_set_intr
;
850 sc
->intmask
= sc
->irstat
= sc
->itstat
= 0;
852 /* Init task queue */
853 sc
->fc
.taskqueue
= fw_taskqueue_create_fast("fw_taskq", M_WAITOK
,
854 fw_taskqueue_thread_enqueue
, &sc
->fc
.taskqueue
);
855 fw_taskqueue_start_threads(&sc
->fc
.taskqueue
, 1, PI_NET
, "fw%d_taskq",
857 FW_TASK_INIT(&sc
->fwohci_task_busreset
, 2, fwohci_task_busreset
, sc
);
858 FW_TASK_INIT(&sc
->fwohci_task_sid
, 1, fwohci_task_sid
, sc
);
859 FW_TASK_INIT(&sc
->fwohci_task_dma
, 0, fwohci_task_dma
, sc
);
862 fwohci_reset(sc
, dev
);
869 fwohci_timeout(void *arg
)
871 struct fwohci_softc
*sc
;
873 sc
= (struct fwohci_softc
*)arg
;
877 fwohci_cyctimer(struct firewire_comm
*fc
)
879 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
880 return(OREAD(sc
, OHCI_CYCLETIMER
));
888 if (sc
->sid_buf
!= NULL
)
889 fwdma_free(&sc
->fc
, &sc
->sid_dma
);
890 if (sc
->fc
.config_rom
!= NULL
)
891 fwdma_free(&sc
->fc
, &sc
->crom_dma
);
893 fwohci_db_free(&sc
->arrq
);
894 fwohci_db_free(&sc
->arrs
);
896 fwohci_db_free(&sc
->atrq
);
897 fwohci_db_free(&sc
->atrs
);
899 for( i
= 0 ; i
< sc
->fc
.nisodma
; i
++ ){
900 fwohci_db_free(&sc
->it
[i
]);
901 fwohci_db_free(&sc
->ir
[i
]);
908 #define LAST_DB(dbtr, db) do { \
909 struct fwohcidb_tr *_dbtr = (dbtr); \
910 int _cnt = _dbtr->dbcnt; \
911 db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \
915 fwohci_execute_db(void *arg
, bus_dma_segment_t
*segs
, int nseg
, int error
)
917 struct fwohcidb_tr
*db_tr
;
919 bus_dma_segment_t
*s
;
922 db_tr
= (struct fwohcidb_tr
*)arg
;
923 db
= &db_tr
->db
[db_tr
->dbcnt
];
925 if (firewire_debug
|| error
!= EFBIG
)
926 printf("fwohci_execute_db: error=%d\n", error
);
929 for (i
= 0; i
< nseg
; i
++) {
931 FWOHCI_DMA_WRITE(db
->db
.desc
.addr
, s
->ds_addr
);
932 FWOHCI_DMA_WRITE(db
->db
.desc
.cmd
, s
->ds_len
);
933 FWOHCI_DMA_WRITE(db
->db
.desc
.res
, 0);
940 fwohci_execute_db2(void *arg
, bus_dma_segment_t
*segs
, int nseg
,
941 bus_size_t size
, int error
)
943 fwohci_execute_db(arg
, segs
, nseg
, error
);
947 fwohci_start(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
950 int tcode
, hdr_len
, pl_off
;
953 struct fw_xfer
*xfer
;
955 struct fwohci_txpkthdr
*ohcifp
;
956 struct fwohcidb_tr
*db_tr
;
959 const struct tcode_info
*info
;
960 static int maxdesc
=0;
962 FW_GLOCK_ASSERT(&sc
->fc
);
964 if(&sc
->atrq
== dbch
){
966 }else if(&sc
->atrs
== dbch
){
972 if (dbch
->flags
& FWOHCI_DBCH_FULL
)
976 fwdma_sync_multiseg_all(dbch
->am
,
977 BUS_DMASYNC_POSTREAD
| BUS_DMASYNC_POSTWRITE
);
980 xfer
= STAILQ_FIRST(&dbch
->xferq
.q
);
985 if(dbch
->xferq
.queued
== 0 ){
986 fw_printf(sc
->fc
.dev
, "TX queue empty\n");
989 STAILQ_REMOVE_HEAD(&dbch
->xferq
.q
, link
);
991 xfer
->flag
= FWXF_START
;
993 fp
= &xfer
->send
.hdr
;
994 tcode
= fp
->mode
.common
.tcode
;
996 ohcifp
= (struct fwohci_txpkthdr
*) db_tr
->db
[1].db
.immed
;
997 info
= &tinfo
[tcode
];
998 hdr_len
= pl_off
= info
->hdr_len
;
1000 ld
= &ohcifp
->mode
.ld
[0];
1001 ld
[0] = ld
[1] = ld
[2] = ld
[3] = 0;
1002 for( i
= 0 ; i
< pl_off
; i
+= 4)
1003 ld
[i
/4] = fp
->mode
.ld
[i
/4];
1005 ohcifp
->mode
.common
.spd
= xfer
->send
.spd
& 0x7;
1006 if (tcode
== FWTCODE_STREAM
){
1008 ohcifp
->mode
.stream
.len
= fp
->mode
.stream
.len
;
1009 } else if (tcode
== FWTCODE_PHY
) {
1011 ld
[1] = fp
->mode
.ld
[1];
1012 ld
[2] = fp
->mode
.ld
[2];
1013 ohcifp
->mode
.common
.spd
= 0;
1014 ohcifp
->mode
.common
.tcode
= FWOHCITCODE_PHY
;
1016 ohcifp
->mode
.asycomm
.dst
= fp
->mode
.hdr
.dst
;
1017 ohcifp
->mode
.asycomm
.srcbus
= OHCI_ASYSRCBUS
;
1018 ohcifp
->mode
.asycomm
.tlrt
|= FWRETRY_X
;
1021 FWOHCI_DMA_WRITE(db
->db
.desc
.cmd
,
1022 OHCI_OUTPUT_MORE
| OHCI_KEY_ST2
| hdr_len
);
1023 FWOHCI_DMA_WRITE(db
->db
.desc
.addr
, 0);
1024 FWOHCI_DMA_WRITE(db
->db
.desc
.res
, 0);
1025 /* Specify bound timer of asy. responce */
1026 if(&sc
->atrs
== dbch
){
1027 FWOHCI_DMA_WRITE(db
->db
.desc
.res
,
1028 (OREAD(sc
, OHCI_CYCLETIMER
) >> 12) + (1 << 13));
1030 #if BYTE_ORDER == BIG_ENDIAN
1031 if (tcode
== FWTCODE_WREQQ
|| tcode
== FWTCODE_RRESQ
)
1033 for (i
= 0; i
< hdr_len
/4; i
++)
1034 FWOHCI_DMA_WRITE(ld
[i
], ld
[i
]);
1039 db
= &db_tr
->db
[db_tr
->dbcnt
];
1040 if (xfer
->send
.pay_len
> 0) {
1042 /* handle payload */
1043 if (xfer
->mbuf
== NULL
) {
1044 err
= fw_bus_dmamap_load(dbch
->dmat
, db_tr
->dma_map
,
1045 &xfer
->send
.payload
[0], xfer
->send
.pay_len
,
1046 fwohci_execute_db
, db_tr
,
1049 /* XXX we can handle only 6 (=8-2) mbuf chains */
1050 err
= fw_bus_dmamap_load_mbuf(dbch
->dmat
,
1051 db_tr
->dma_map
, xfer
->mbuf
,
1052 fwohci_execute_db2
, db_tr
,
1058 fw_printf(sc
->fc
.dev
, "EFBIG.\n");
1059 m0
= m_getcl(M_DONTWAIT
, MT_DATA
, M_PKTHDR
);
1061 m_copydata(xfer
->mbuf
, 0,
1062 xfer
->mbuf
->m_pkthdr
.len
,
1064 m0
->m_len
= m0
->m_pkthdr
.len
=
1065 xfer
->mbuf
->m_pkthdr
.len
;
1066 m_freem(xfer
->mbuf
);
1070 fw_printf(sc
->fc
.dev
, "m_getcl failed.\n");
1074 printf("dmamap_load: err=%d\n", err
);
1075 fw_bus_dmamap_sync(dbch
->dmat
, db_tr
->dma_map
,
1076 BUS_DMASYNC_PREWRITE
);
1077 #if 0 /* OHCI_OUTPUT_MODE == 0 */
1078 for (i
= 2; i
< db_tr
->dbcnt
; i
++)
1079 FWOHCI_DMA_SET(db_tr
->db
[i
].db
.desc
.cmd
,
1083 if (maxdesc
< db_tr
->dbcnt
) {
1084 maxdesc
= db_tr
->dbcnt
;
1086 fw_printf(sc
->fc
.dev
, "maxdesc: %d\n", maxdesc
);
1090 FWOHCI_DMA_SET(db
->db
.desc
.cmd
,
1091 OHCI_OUTPUT_LAST
| OHCI_INTERRUPT_ALWAYS
| OHCI_BRANCH_ALWAYS
);
1092 FWOHCI_DMA_WRITE(db
->db
.desc
.depend
,
1093 STAILQ_NEXT(db_tr
, link
)->bus_addr
);
1096 fsegment
= db_tr
->dbcnt
;
1097 if (dbch
->pdb_tr
!= NULL
) {
1098 LAST_DB(dbch
->pdb_tr
, db
);
1099 FWOHCI_DMA_SET(db
->db
.desc
.depend
, db_tr
->dbcnt
);
1101 dbch
->xferq
.queued
++;
1102 dbch
->pdb_tr
= db_tr
;
1103 db_tr
= STAILQ_NEXT(db_tr
, link
);
1104 if(db_tr
!= dbch
->bottom
){
1107 fw_printf(sc
->fc
.dev
, "fwohci_start: lack of db_trq\n");
1108 dbch
->flags
|= FWOHCI_DBCH_FULL
;
1112 fwdma_sync_multiseg_all(dbch
->am
,
1113 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
1115 if(dbch
->xferq
.flag
& FWXFERQ_RUNNING
) {
1116 OWRITE(sc
, OHCI_DMACTL(off
), OHCI_CNTL_DMA_WAKE
);
1119 fw_printf(sc
->fc
.dev
, "start AT DMA status=%x\n",
1120 OREAD(sc
, OHCI_DMACTL(off
)));
1121 OWRITE(sc
, OHCI_DMACMD(off
), dbch
->top
->bus_addr
| fsegment
);
1122 OWRITE(sc
, OHCI_DMACTL(off
), OHCI_CNTL_DMA_RUN
);
1123 dbch
->xferq
.flag
|= FWXFERQ_RUNNING
;
1125 CTR0(KTR_DEV
, "start kick done");
1126 CTR0(KTR_DEV
, "start kick done2");
1134 fwohci_start_atq(struct firewire_comm
*fc
)
1136 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1138 fwohci_start( sc
, &(sc
->atrq
));
1139 FW_GUNLOCK(&sc
->fc
);
1144 fwohci_start_ats(struct firewire_comm
*fc
)
1146 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1148 fwohci_start( sc
, &(sc
->atrs
));
1149 FW_GUNLOCK(&sc
->fc
);
1154 fwohci_txd(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
1157 struct fwohcidb_tr
*tr
;
1158 struct fwohcidb
*db
;
1159 struct fw_xfer
*xfer
;
1163 struct firewire_comm
*fc
= (struct firewire_comm
*)sc
;
1165 if(&sc
->atrq
== dbch
){
1168 }else if(&sc
->atrs
== dbch
){
1177 fwdma_sync_multiseg_all(dbch
->am
,
1178 BUS_DMASYNC_POSTREAD
| BUS_DMASYNC_POSTWRITE
);
1179 while(dbch
->xferq
.queued
> 0){
1181 status
= FWOHCI_DMA_READ(db
->db
.desc
.res
) >> OHCI_STATUS_SHIFT
;
1182 if(!(status
& OHCI_CNTL_DMA_ACTIVE
)){
1183 if (fc
->status
!= FWBUSINIT
)
1184 /* maybe out of order?? */
1187 if (tr
->xfer
->send
.pay_len
> 0) {
1188 fw_bus_dmamap_sync(dbch
->dmat
, tr
->dma_map
,
1189 BUS_DMASYNC_POSTWRITE
);
1190 fw_bus_dmamap_unload(dbch
->dmat
, tr
->dma_map
);
1193 if (firewire_debug
> 1)
1196 if(status
& OHCI_CNTL_DMA_DEAD
) {
1198 OWRITE(sc
, OHCI_DMACTLCLR(off
), OHCI_CNTL_DMA_RUN
);
1199 fw_printf(sc
->fc
.dev
, "force reset AT FIFO\n");
1200 OWRITE(sc
, OHCI_HCCCTLCLR
, OHCI_HCC_LINKEN
);
1201 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_LPS
| OHCI_HCC_LINKEN
);
1202 OWRITE(sc
, OHCI_DMACTLCLR(off
), OHCI_CNTL_DMA_RUN
);
1204 stat
= status
& FWOHCIEV_MASK
;
1206 case FWOHCIEV_ACKPEND
:
1207 CTR0(KTR_DEV
, "txd: ack pending");
1209 case FWOHCIEV_ACKCOMPL
:
1212 case FWOHCIEV_ACKBSA
:
1213 case FWOHCIEV_ACKBSB
:
1214 case FWOHCIEV_ACKBSX
:
1215 fw_printf(sc
->fc
.dev
, "txd err=%2x %s\n", stat
,
1219 case FWOHCIEV_FLUSHED
:
1220 case FWOHCIEV_ACKTARD
:
1221 fw_printf(sc
->fc
.dev
, "txd err=%2x %s\n", stat
,
1225 case FWOHCIEV_MISSACK
:
1226 case FWOHCIEV_UNDRRUN
:
1227 case FWOHCIEV_OVRRUN
:
1228 case FWOHCIEV_DESCERR
:
1229 case FWOHCIEV_DTRDERR
:
1230 case FWOHCIEV_TIMEOUT
:
1231 case FWOHCIEV_TCODERR
:
1232 case FWOHCIEV_UNKNOWN
:
1233 case FWOHCIEV_ACKDERR
:
1234 case FWOHCIEV_ACKTERR
:
1236 fw_printf(sc
->fc
.dev
, "txd err=%2x %s\n",
1237 stat
, fwohcicode
[stat
]);
1241 if (tr
->xfer
!= NULL
) {
1243 CTR0(KTR_DEV
, "txd");
1244 if (xfer
->flag
& FWXF_RCVD
) {
1247 printf("already rcvd\n");
1251 microtime(&xfer
->tv
);
1252 xfer
->flag
= FWXF_SENT
;
1254 xfer
->flag
= FWXF_BUSY
;
1256 xfer
->recv
.pay_len
= 0;
1258 } else if (stat
!= FWOHCIEV_ACKPEND
) {
1259 if (stat
!= FWOHCIEV_ACKCOMPL
)
1260 xfer
->flag
= FWXF_SENTERR
;
1262 xfer
->recv
.pay_len
= 0;
1267 * The watchdog timer takes care of split
1268 * transcation timeout for ACKPEND case.
1271 printf("this shouldn't happen\n");
1274 dbch
->xferq
.queued
--;
1278 fwdma_sync_multiseg_all(dbch
->am
, BUS_DMASYNC_PREREAD
);
1280 tr
= STAILQ_NEXT(tr
, link
);
1282 if (dbch
->bottom
== dbch
->top
) {
1283 /* we reaches the end of context program */
1284 if (firewire_debug
&& dbch
->xferq
.queued
> 0)
1285 printf("queued > 0\n");
1290 if ((dbch
->flags
& FWOHCI_DBCH_FULL
) && packets
> 0) {
1291 printf("make free slot\n");
1292 dbch
->flags
&= ~FWOHCI_DBCH_FULL
;
1294 fwohci_start(sc
, dbch
);
1297 fwdma_sync_multiseg_all(
1298 dbch
->am
, BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
1303 fwohci_db_free(struct fwohci_dbch
*dbch
)
1305 struct fwohcidb_tr
*db_tr
;
1308 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) == 0)
1311 for(db_tr
= STAILQ_FIRST(&dbch
->db_trq
), idb
= 0; idb
< dbch
->ndb
;
1312 db_tr
= STAILQ_NEXT(db_tr
, link
), idb
++){
1313 if ((dbch
->xferq
.flag
& FWXFERQ_EXTBUF
) == 0 &&
1314 db_tr
->buf
!= NULL
) {
1315 fwdma_free_size(dbch
->dmat
, db_tr
->dma_map
,
1316 db_tr
->buf
, dbch
->xferq
.psize
);
1318 } else if (db_tr
->dma_map
!= NULL
)
1319 fw_bus_dmamap_destroy(dbch
->dmat
, db_tr
->dma_map
);
1322 db_tr
= STAILQ_FIRST(&dbch
->db_trq
);
1323 fwdma_free_multiseg(dbch
->am
);
1325 STAILQ_INIT(&dbch
->db_trq
);
1326 dbch
->flags
&= ~FWOHCI_DBCH_INIT
;
1327 seldestroy(&dbch
->xferq
.rsel
);
1331 fwohci_db_init(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
1334 struct fwohcidb_tr
*db_tr
;
1336 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) != 0)
1339 /* create dma_tag for buffers */
1340 #define MAX_REQCOUNT 0xffff
1341 if (fw_bus_dma_tag_create(/*parent*/ sc
->fc
.dmat
,
1342 /*alignment*/ 1, /*boundary*/ 0,
1343 /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT
,
1344 /*highaddr*/ BUS_SPACE_MAXADDR
,
1345 /*filter*/NULL
, /*filterarg*/NULL
,
1346 /*maxsize*/ dbch
->xferq
.psize
,
1347 /*nsegments*/ dbch
->ndesc
> 3 ? dbch
->ndesc
- 2 : 1,
1348 /*maxsegsz*/ MAX_REQCOUNT
,
1350 /*lockfunc*/busdma_lock_mutex
,
1351 /*lockarg*/FW_GMTX(&sc
->fc
),
1355 /* allocate DB entries and attach one to each DMA channels */
1356 /* DB entry must start at 16 bytes bounary. */
1357 STAILQ_INIT(&dbch
->db_trq
);
1358 db_tr
= (struct fwohcidb_tr
*)
1359 malloc(sizeof(struct fwohcidb_tr
) * dbch
->ndb
,
1360 M_FW
, M_WAITOK
| M_ZERO
);
1362 printf("fwohci_db_init: malloc(1) failed\n");
1366 #define DB_SIZE(x) (sizeof(struct fwohcidb) * (x)->ndesc)
1367 dbch
->am
= fwdma_malloc_multiseg(&sc
->fc
, DB_SIZE(dbch
),
1368 DB_SIZE(dbch
), dbch
->ndb
, BUS_DMA_WAITOK
| BUS_DMA_COHERENT
);
1369 if (dbch
->am
== NULL
) {
1370 printf("fwohci_db_init: fwdma_malloc_multiseg failed\n");
1374 /* Attach DB to DMA ch. */
1375 for(idb
= 0 ; idb
< dbch
->ndb
; idb
++){
1377 db_tr
->db
= (struct fwohcidb
*)fwdma_v_addr(dbch
->am
, idb
);
1378 db_tr
->bus_addr
= fwdma_bus_addr(dbch
->am
, idb
);
1379 /* create dmamap for buffers */
1380 /* XXX do we need 4bytes alignment tag? */
1381 /* XXX don't alloc dma_map for AR */
1382 if (fw_bus_dmamap_create(dbch
->dmat
, 0, &db_tr
->dma_map
) != 0) {
1383 printf("fw_bus_dmamap_create failed\n");
1384 dbch
->flags
= FWOHCI_DBCH_INIT
; /* XXX fake */
1385 fwohci_db_free(dbch
);
1388 STAILQ_INSERT_TAIL(&dbch
->db_trq
, db_tr
, link
);
1389 if (dbch
->xferq
.flag
& FWXFERQ_EXTBUF
) {
1390 if (idb
% dbch
->xferq
.bnpacket
== 0)
1391 dbch
->xferq
.bulkxfer
[idb
/ dbch
->xferq
.bnpacket
1392 ].start
= (void *)db_tr
;
1393 if ((idb
+ 1) % dbch
->xferq
.bnpacket
== 0)
1394 dbch
->xferq
.bulkxfer
[idb
/ dbch
->xferq
.bnpacket
1395 ].end
= (void *)db_tr
;
1399 STAILQ_LAST(&dbch
->db_trq
, fwohcidb_tr
,link
)->link
.stqe_next
1400 = STAILQ_FIRST(&dbch
->db_trq
);
1402 dbch
->xferq
.queued
= 0;
1403 dbch
->pdb_tr
= NULL
;
1404 dbch
->top
= STAILQ_FIRST(&dbch
->db_trq
);
1405 dbch
->bottom
= dbch
->top
;
1406 dbch
->flags
= FWOHCI_DBCH_INIT
;
1407 selinit(&dbch
->xferq
.rsel
);
1411 fwohci_itx_disable(struct firewire_comm
*fc
, int dmach
)
1413 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1416 OWRITE(sc
, OHCI_ITCTLCLR(dmach
),
1417 OHCI_CNTL_DMA_RUN
| OHCI_CNTL_CYCMATCH_S
);
1418 OWRITE(sc
, OHCI_IT_MASKCLR
, 1 << dmach
);
1419 OWRITE(sc
, OHCI_IT_STATCLR
, 1 << dmach
);
1420 /* XXX we cannot free buffers until the DMA really stops */
1421 tsleep((void *)&sleepch
, FWPRI
, "fwitxd", hz
);
1422 fwohci_db_free(&sc
->it
[dmach
]);
1423 sc
->it
[dmach
].xferq
.flag
&= ~FWXFERQ_RUNNING
;
1428 fwohci_irx_disable(struct firewire_comm
*fc
, int dmach
)
1430 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1433 OWRITE(sc
, OHCI_IRCTLCLR(dmach
), OHCI_CNTL_DMA_RUN
);
1434 OWRITE(sc
, OHCI_IR_MASKCLR
, 1 << dmach
);
1435 OWRITE(sc
, OHCI_IR_STATCLR
, 1 << dmach
);
1436 /* XXX we cannot free buffers until the DMA really stops */
1437 tsleep((void *)&sleepch
, FWPRI
, "fwirxd", hz
);
1438 fwohci_db_free(&sc
->ir
[dmach
]);
1439 sc
->ir
[dmach
].xferq
.flag
&= ~FWXFERQ_RUNNING
;
1443 #if BYTE_ORDER == BIG_ENDIAN
1445 fwohci_irx_post (struct firewire_comm
*fc
, uint32_t *qld
)
1447 qld
[0] = FWOHCI_DMA_READ(qld
[0]);
1453 fwohci_tx_enable(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
1456 int idb
, z
, i
, dmach
= 0, ldesc
;
1458 struct fwohcidb_tr
*db_tr
;
1459 struct fwohcidb
*db
;
1461 if(!(dbch
->xferq
.flag
& FWXFERQ_EXTBUF
)){
1466 for(dmach
= 0 ; dmach
< sc
->fc
.nisodma
; dmach
++){
1467 if( &sc
->it
[dmach
] == dbch
){
1468 off
= OHCI_ITOFF(dmach
);
1476 if(dbch
->xferq
.flag
& FWXFERQ_RUNNING
)
1478 dbch
->xferq
.flag
|= FWXFERQ_RUNNING
;
1479 for( i
= 0, dbch
->bottom
= dbch
->top
; i
< (dbch
->ndb
- 1); i
++){
1480 dbch
->bottom
= STAILQ_NEXT(dbch
->bottom
, link
);
1483 for (idb
= 0; idb
< dbch
->ndb
; idb
++) {
1484 fwohci_add_tx_buf(dbch
, db_tr
, idb
);
1485 if(STAILQ_NEXT(db_tr
, link
) == NULL
){
1489 ldesc
= db_tr
->dbcnt
- 1;
1490 FWOHCI_DMA_WRITE(db
[0].db
.desc
.depend
,
1491 STAILQ_NEXT(db_tr
, link
)->bus_addr
| z
);
1492 db
[ldesc
].db
.desc
.depend
= db
[0].db
.desc
.depend
;
1493 if(dbch
->xferq
.flag
& FWXFERQ_EXTBUF
){
1494 if(((idb
+ 1 ) % dbch
->xferq
.bnpacket
) == 0){
1496 db
[ldesc
].db
.desc
.cmd
,
1497 OHCI_INTERRUPT_ALWAYS
);
1498 /* OHCI 1.1 and above */
1501 OHCI_INTERRUPT_ALWAYS
);
1504 db_tr
= STAILQ_NEXT(db_tr
, link
);
1507 dbch
->bottom
->db
[dbch
->bottom
->dbcnt
- 1].db
.desc
.depend
, 0xf);
1512 fwohci_rx_enable(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
)
1515 int idb
, z
, i
, dmach
= 0, ldesc
;
1517 struct fwohcidb_tr
*db_tr
;
1518 struct fwohcidb
*db
;
1521 if(&sc
->arrq
== dbch
){
1523 }else if(&sc
->arrs
== dbch
){
1526 for(dmach
= 0 ; dmach
< sc
->fc
.nisodma
; dmach
++){
1527 if( &sc
->ir
[dmach
] == dbch
){
1528 off
= OHCI_IROFF(dmach
);
1537 if(dbch
->xferq
.flag
& FWXFERQ_STREAM
){
1538 if(dbch
->xferq
.flag
& FWXFERQ_RUNNING
)
1541 if(dbch
->xferq
.flag
& FWXFERQ_RUNNING
){
1546 dbch
->xferq
.flag
|= FWXFERQ_RUNNING
;
1547 dbch
->top
= STAILQ_FIRST(&dbch
->db_trq
);
1548 for( i
= 0, dbch
->bottom
= dbch
->top
; i
< (dbch
->ndb
- 1); i
++){
1549 dbch
->bottom
= STAILQ_NEXT(dbch
->bottom
, link
);
1552 if (db_tr
->dbcnt
!= 0)
1554 for (idb
= 0; idb
< dbch
->ndb
; idb
++) {
1555 fwohci_add_rx_buf(dbch
, db_tr
, idb
, &sc
->dummy_dma
);
1556 if (STAILQ_NEXT(db_tr
, link
) == NULL
)
1559 ldesc
= db_tr
->dbcnt
- 1;
1560 FWOHCI_DMA_WRITE(db
[ldesc
].db
.desc
.depend
,
1561 STAILQ_NEXT(db_tr
, link
)->bus_addr
| z
);
1562 if(dbch
->xferq
.flag
& FWXFERQ_EXTBUF
){
1563 if(((idb
+ 1 ) % dbch
->xferq
.bnpacket
) == 0){
1565 db
[ldesc
].db
.desc
.cmd
,
1566 OHCI_INTERRUPT_ALWAYS
);
1568 db
[ldesc
].db
.desc
.depend
,
1572 db_tr
= STAILQ_NEXT(db_tr
, link
);
1575 dbch
->bottom
->db
[db_tr
->dbcnt
- 1].db
.desc
.depend
, 0xf);
1576 dbch
->buf_offset
= 0;
1578 fwdma_sync_multiseg_all(dbch
->am
,
1579 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
1580 if(dbch
->xferq
.flag
& FWXFERQ_STREAM
){
1583 OWRITE(sc
, OHCI_DMACMD(off
), dbch
->top
->bus_addr
| z
);
1585 OWRITE(sc
, OHCI_DMACTL(off
), OHCI_CNTL_DMA_RUN
);
1590 fwohci_next_cycle(struct firewire_comm
*fc
, int cycle_now
)
1592 int sec
, cycle
, cycle_match
;
1594 cycle
= cycle_now
& 0x1fff;
1595 sec
= cycle_now
>> 13;
1596 #define CYCLE_MOD 0x10
1598 #define CYCLE_DELAY 8 /* min delay to start DMA */
1600 #define CYCLE_DELAY 7000 /* min delay to start DMA */
1602 cycle
= cycle
+ CYCLE_DELAY
;
1603 if (cycle
>= 8000) {
1607 cycle
= roundup2(cycle
, CYCLE_MOD
);
1608 if (cycle
>= 8000) {
1615 cycle_match
= ((sec
<< 13) | cycle
) & 0x7ffff;
1617 return(cycle_match
);
1621 fwohci_itxbuf_enable(struct firewire_comm
*fc
, int dmach
)
1623 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1625 unsigned short tag
, ich
;
1626 struct fwohci_dbch
*dbch
;
1627 int cycle_match
, cycle_now
, s
, ldesc
;
1629 struct fw_bulkxfer
*first
, *chunk
, *prev
;
1630 struct fw_xferq
*it
;
1632 dbch
= &sc
->it
[dmach
];
1635 tag
= (it
->flag
>> 6) & 3;
1636 ich
= it
->flag
& 0x3f;
1637 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) == 0) {
1638 dbch
->ndb
= it
->bnpacket
* it
->bnchunk
;
1640 fwohci_db_init(sc
, dbch
);
1641 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) == 0)
1644 err
= fwohci_tx_enable(sc
, dbch
);
1649 ldesc
= dbch
->ndesc
- 1;
1652 prev
= STAILQ_LAST(&it
->stdma
, fw_bulkxfer
, link
);
1653 while ((chunk
= STAILQ_FIRST(&it
->stvalid
)) != NULL
) {
1654 struct fwohcidb
*db
;
1656 fwdma_sync_multiseg(it
->buf
, chunk
->poffset
, it
->bnpacket
,
1657 BUS_DMASYNC_PREWRITE
);
1658 fwohci_txbufdb(sc
, dmach
, chunk
);
1660 db
= ((struct fwohcidb_tr
*)(prev
->end
))->db
;
1661 #if 0 /* XXX necessary? */
1662 FWOHCI_DMA_SET(db
[ldesc
].db
.desc
.cmd
,
1663 OHCI_BRANCH_ALWAYS
);
1665 #if 0 /* if bulkxfer->npacket changes */
1666 db
[ldesc
].db
.desc
.depend
= db
[0].db
.desc
.depend
=
1667 ((struct fwohcidb_tr
*)
1668 (chunk
->start
))->bus_addr
| dbch
->ndesc
;
1670 FWOHCI_DMA_SET(db
[0].db
.desc
.depend
, dbch
->ndesc
);
1671 FWOHCI_DMA_SET(db
[ldesc
].db
.desc
.depend
, dbch
->ndesc
);
1674 STAILQ_REMOVE_HEAD(&it
->stvalid
, link
);
1675 STAILQ_INSERT_TAIL(&it
->stdma
, chunk
, link
);
1679 fwdma_sync_multiseg_all(dbch
->am
,
1680 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
1682 stat
= OREAD(sc
, OHCI_ITCTL(dmach
));
1683 if (firewire_debug
&& (stat
& OHCI_CNTL_CYCMATCH_S
))
1684 printf("stat 0x%x\n", stat
);
1686 if (stat
& (OHCI_CNTL_DMA_ACTIVE
| OHCI_CNTL_CYCMATCH_S
))
1690 OWRITE(sc
, OHCI_ITCTLCLR(dmach
), OHCI_CNTL_DMA_RUN
);
1692 OWRITE(sc
, OHCI_IT_MASKCLR
, 1 << dmach
);
1693 OWRITE(sc
, OHCI_IT_STATCLR
, 1 << dmach
);
1694 OWRITE(sc
, OHCI_IT_MASK
, 1 << dmach
);
1695 OWRITE(sc
, FWOHCI_INTMASK
, OHCI_INT_DMA_IT
);
1697 first
= STAILQ_FIRST(&it
->stdma
);
1698 OWRITE(sc
, OHCI_ITCMD(dmach
),
1699 ((struct fwohcidb_tr
*)(first
->start
))->bus_addr
| dbch
->ndesc
);
1700 if (firewire_debug
> 1) {
1701 printf("fwohci_itxbuf_enable: kick 0x%08x\n", stat
);
1703 dump_dma(sc
, ITX_CH
+ dmach
);
1706 if ((stat
& OHCI_CNTL_DMA_RUN
) == 0) {
1708 /* Don't start until all chunks are buffered */
1709 if (STAILQ_FIRST(&it
->stfree
) != NULL
)
1713 /* Clear cycle match counter bits */
1714 OWRITE(sc
, OHCI_ITCTLCLR(dmach
), 0xffff0000);
1716 /* 2bit second + 13bit cycle */
1717 cycle_now
= (fc
->cyctimer(fc
) >> 12) & 0x7fff;
1718 cycle_match
= fwohci_next_cycle(fc
, cycle_now
);
1720 OWRITE(sc
, OHCI_ITCTL(dmach
),
1721 OHCI_CNTL_CYCMATCH_S
| (cycle_match
<< 16)
1722 | OHCI_CNTL_DMA_RUN
);
1724 OWRITE(sc
, OHCI_ITCTL(dmach
), OHCI_CNTL_DMA_RUN
);
1726 if (firewire_debug
> 1) {
1727 printf("cycle_match: 0x%04x->0x%04x\n",
1728 cycle_now
, cycle_match
);
1729 dump_dma(sc
, ITX_CH
+ dmach
);
1730 dump_db(sc
, ITX_CH
+ dmach
);
1732 } else if ((stat
& OHCI_CNTL_CYCMATCH_S
) == 0) {
1733 fw_printf(sc
->fc
.dev
, "IT DMA underrun (0x%08x)\n", stat
);
1734 OWRITE(sc
, OHCI_ITCTL(dmach
), OHCI_CNTL_DMA_WAKE
);
1741 fwohci_irx_enable(struct firewire_comm
*fc
, int dmach
)
1743 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
1744 int err
= 0, s
, ldesc
;
1745 unsigned short tag
, ich
;
1747 struct fwohci_dbch
*dbch
;
1748 struct fwohcidb_tr
*db_tr
;
1749 struct fw_bulkxfer
*first
, *prev
, *chunk
;
1750 struct fw_xferq
*ir
;
1752 dbch
= &sc
->ir
[dmach
];
1755 if ((ir
->flag
& FWXFERQ_RUNNING
) == 0) {
1756 tag
= (ir
->flag
>> 6) & 3;
1757 ich
= ir
->flag
& 0x3f;
1758 OWRITE(sc
, OHCI_IRMATCH(dmach
), tagbit
[tag
] | ich
);
1761 dbch
->ndb
= ir
->bnpacket
* ir
->bnchunk
;
1763 fwohci_db_init(sc
, dbch
);
1764 if ((dbch
->flags
& FWOHCI_DBCH_INIT
) == 0)
1766 err
= fwohci_rx_enable(sc
, dbch
);
1771 first
= STAILQ_FIRST(&ir
->stfree
);
1772 if (first
== NULL
) {
1773 fw_printf(fc
->dev
, "IR DMA no free chunk\n");
1777 ldesc
= dbch
->ndesc
- 1;
1779 if ((ir
->flag
& FWXFERQ_HANDLER
) == 0)
1781 prev
= STAILQ_LAST(&ir
->stdma
, fw_bulkxfer
, link
);
1782 while ((chunk
= STAILQ_FIRST(&ir
->stfree
)) != NULL
) {
1783 struct fwohcidb
*db
;
1785 #if 1 /* XXX for if_fwe */
1786 if (chunk
->mbuf
!= NULL
) {
1787 db_tr
= (struct fwohcidb_tr
*)(chunk
->start
);
1789 err
= fw_bus_dmamap_load_mbuf(
1790 dbch
->dmat
, db_tr
->dma_map
,
1791 chunk
->mbuf
, fwohci_execute_db2
, db_tr
,
1793 FWOHCI_DMA_SET(db_tr
->db
[1].db
.desc
.cmd
,
1794 OHCI_UPDATE
| OHCI_INPUT_LAST
|
1795 OHCI_INTERRUPT_ALWAYS
| OHCI_BRANCH_ALWAYS
);
1798 db
= ((struct fwohcidb_tr
*)(chunk
->end
))->db
;
1799 FWOHCI_DMA_WRITE(db
[ldesc
].db
.desc
.res
, 0);
1800 FWOHCI_DMA_CLEAR(db
[ldesc
].db
.desc
.depend
, 0xf);
1802 db
= ((struct fwohcidb_tr
*)(prev
->end
))->db
;
1803 FWOHCI_DMA_SET(db
[ldesc
].db
.desc
.depend
, dbch
->ndesc
);
1805 STAILQ_REMOVE_HEAD(&ir
->stfree
, link
);
1806 STAILQ_INSERT_TAIL(&ir
->stdma
, chunk
, link
);
1809 if ((ir
->flag
& FWXFERQ_HANDLER
) == 0)
1811 fwdma_sync_multiseg_all(dbch
->am
,
1812 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
1814 stat
= OREAD(sc
, OHCI_IRCTL(dmach
));
1815 if (stat
& OHCI_CNTL_DMA_ACTIVE
)
1817 if (stat
& OHCI_CNTL_DMA_RUN
) {
1818 OWRITE(sc
, OHCI_IRCTLCLR(dmach
), OHCI_CNTL_DMA_RUN
);
1819 fw_printf(sc
->fc
.dev
, "IR DMA overrun (0x%08x)\n", stat
);
1823 printf("start IR DMA 0x%x\n", stat
);
1824 OWRITE(sc
, OHCI_IR_MASKCLR
, 1 << dmach
);
1825 OWRITE(sc
, OHCI_IR_STATCLR
, 1 << dmach
);
1826 OWRITE(sc
, OHCI_IR_MASK
, 1 << dmach
);
1827 OWRITE(sc
, OHCI_IRCTLCLR(dmach
), 0xf0000000);
1828 OWRITE(sc
, OHCI_IRCTL(dmach
), OHCI_CNTL_ISOHDR
);
1829 OWRITE(sc
, OHCI_IRCMD(dmach
),
1830 ((struct fwohcidb_tr
*)(first
->start
))->bus_addr
1832 OWRITE(sc
, OHCI_IRCTL(dmach
), OHCI_CNTL_DMA_RUN
);
1833 OWRITE(sc
, FWOHCI_INTMASK
, OHCI_INT_DMA_IR
);
1835 dump_db(sc
, IRX_CH
+ dmach
);
1841 fwohci_stop(struct fwohci_softc
*sc
, device_t dev
)
1845 /* Now stopping all DMA channel */
1846 OWRITE(sc
, OHCI_ARQCTLCLR
, OHCI_CNTL_DMA_RUN
);
1847 OWRITE(sc
, OHCI_ARSCTLCLR
, OHCI_CNTL_DMA_RUN
);
1848 OWRITE(sc
, OHCI_ATQCTLCLR
, OHCI_CNTL_DMA_RUN
);
1849 OWRITE(sc
, OHCI_ATSCTLCLR
, OHCI_CNTL_DMA_RUN
);
1851 for( i
= 0 ; i
< sc
->fc
.nisodma
; i
++ ){
1852 OWRITE(sc
, OHCI_IRCTLCLR(i
), OHCI_CNTL_DMA_RUN
);
1853 OWRITE(sc
, OHCI_ITCTLCLR(i
), OHCI_CNTL_DMA_RUN
);
1856 if (sc
->fc
.arq
!=0 && sc
->fc
.arq
->maxq
> 0)
1857 fw_drain_txq(&sc
->fc
);
1859 #if 0 /* Let dcons(4) be accessed */
1860 /* Stop interrupt */
1861 OWRITE(sc
, FWOHCI_INTMASKCLR
,
1862 OHCI_INT_EN
| OHCI_INT_ERR
| OHCI_INT_PHY_SID
1864 | OHCI_INT_DMA_ATRQ
| OHCI_INT_DMA_ATRS
1865 | OHCI_INT_DMA_PRRQ
| OHCI_INT_DMA_PRRS
1866 | OHCI_INT_DMA_ARRQ
| OHCI_INT_DMA_ARRS
1867 | OHCI_INT_PHY_BUS_R
);
1869 /* FLUSH FIFO and reset Transmitter/Reciever */
1870 OWRITE(sc
, OHCI_HCCCTL
, OHCI_HCC_RESET
);
1873 /* XXX Link down? Bus reset? */
1878 fwohci_resume(struct fwohci_softc
*sc
, device_t dev
)
1881 struct fw_xferq
*ir
;
1882 struct fw_bulkxfer
*chunk
;
1884 fwohci_reset(sc
, dev
);
1885 /* XXX resume isochronous receive automatically. (how about TX?) */
1886 for(i
= 0; i
< sc
->fc
.nisodma
; i
++) {
1887 ir
= &sc
->ir
[i
].xferq
;
1888 if((ir
->flag
& FWXFERQ_RUNNING
) != 0) {
1889 fw_printf(sc
->fc
.dev
,
1890 "resume iso receive ch: %d\n", i
);
1891 ir
->flag
&= ~FWXFERQ_RUNNING
;
1892 /* requeue stdma to stfree */
1893 while((chunk
= STAILQ_FIRST(&ir
->stdma
)) != NULL
) {
1894 STAILQ_REMOVE_HEAD(&ir
->stdma
, link
);
1895 STAILQ_INSERT_TAIL(&ir
->stfree
, chunk
, link
);
1897 sc
->fc
.irx_enable(&sc
->fc
, i
);
1901 #if defined(__FreeBSD__)
1902 bus_generic_resume(dev
);
1903 #elif defined(__NetBSD__)
1905 extern int firewire_resume(struct firewire_comm
*);
1906 firewire_resume(&sc
->fc
);
1909 sc
->fc
.ibr(&sc
->fc
);
1915 fwohci_dump_intr(struct fwohci_softc
*sc
, uint32_t stat
)
1917 if(stat
& OREAD(sc
, FWOHCI_INTMASK
))
1918 fw_printf(fc
->dev
, "INTERRUPT < %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s> 0x%08x, 0x%08x\n",
1919 stat
& OHCI_INT_EN
? "DMA_EN ":"",
1920 stat
& OHCI_INT_PHY_REG
? "PHY_REG ":"",
1921 stat
& OHCI_INT_CYC_LONG
? "CYC_LONG ":"",
1922 stat
& OHCI_INT_ERR
? "INT_ERR ":"",
1923 stat
& OHCI_INT_CYC_ERR
? "CYC_ERR ":"",
1924 stat
& OHCI_INT_CYC_LOST
? "CYC_LOST ":"",
1925 stat
& OHCI_INT_CYC_64SECOND
? "CYC_64SECOND ":"",
1926 stat
& OHCI_INT_CYC_START
? "CYC_START ":"",
1927 stat
& OHCI_INT_PHY_INT
? "PHY_INT ":"",
1928 stat
& OHCI_INT_PHY_BUS_R
? "BUS_RESET ":"",
1929 stat
& OHCI_INT_PHY_SID
? "SID ":"",
1930 stat
& OHCI_INT_LR_ERR
? "DMA_LR_ERR ":"",
1931 stat
& OHCI_INT_PW_ERR
? "DMA_PW_ERR ":"",
1932 stat
& OHCI_INT_DMA_IR
? "DMA_IR ":"",
1933 stat
& OHCI_INT_DMA_IT
? "DMA_IT " :"",
1934 stat
& OHCI_INT_DMA_PRRS
? "DMA_PRRS " :"",
1935 stat
& OHCI_INT_DMA_PRRQ
? "DMA_PRRQ " :"",
1936 stat
& OHCI_INT_DMA_ARRS
? "DMA_ARRS " :"",
1937 stat
& OHCI_INT_DMA_ARRQ
? "DMA_ARRQ " :"",
1938 stat
& OHCI_INT_DMA_ATRS
? "DMA_ATRS " :"",
1939 stat
& OHCI_INT_DMA_ATRQ
? "DMA_ATRQ " :"",
1940 stat
, OREAD(sc
, FWOHCI_INTMASK
)
1945 fwohci_intr_core(struct fwohci_softc
*sc
, uint32_t stat
, int count
)
1947 struct firewire_comm
*fc
= (struct firewire_comm
*)sc
;
1948 uint32_t node_id
, plen
;
1950 CTR0(KTR_DEV
, "fwohci_intr_core");
1952 if ((stat
& OHCI_INT_PHY_BUS_R
) && (fc
->status
!= FWBUSRESET
)) {
1953 fc
->status
= FWBUSRESET
;
1954 /* Disable bus reset interrupt until sid recv. */
1955 OWRITE(sc
, FWOHCI_INTMASKCLR
, OHCI_INT_PHY_BUS_R
);
1957 fw_printf(fc
->dev
, "BUS reset\n");
1958 OWRITE(sc
, FWOHCI_INTMASKCLR
, OHCI_INT_CYC_LOST
);
1959 OWRITE(sc
, OHCI_LNKCTLCLR
, OHCI_CNTL_CYCSRC
);
1961 OWRITE(sc
, OHCI_ATQCTLCLR
, OHCI_CNTL_DMA_RUN
);
1962 sc
->atrq
.xferq
.flag
&= ~FWXFERQ_RUNNING
;
1963 OWRITE(sc
, OHCI_ATSCTLCLR
, OHCI_CNTL_DMA_RUN
);
1964 sc
->atrs
.xferq
.flag
&= ~FWXFERQ_RUNNING
;
1967 fw_taskqueue_enqueue(sc
->fc
.taskqueue
,
1968 &sc
->fwohci_task_busreset
);
1970 if (stat
& OHCI_INT_PHY_SID
) {
1971 /* Enable bus reset interrupt */
1972 OWRITE(sc
, FWOHCI_INTSTATCLR
, OHCI_INT_PHY_BUS_R
);
1973 OWRITE(sc
, FWOHCI_INTMASK
, OHCI_INT_PHY_BUS_R
);
1975 /* Allow async. request to us */
1976 OWRITE(sc
, OHCI_AREQHI
, 1 << 31);
1977 if (firewire_phydma_enable
) {
1978 /* allow from all nodes */
1979 OWRITE(sc
, OHCI_PREQHI
, 0x7fffffff);
1980 OWRITE(sc
, OHCI_PREQLO
, 0xffffffff);
1981 /* 0 to 4GB regison */
1982 OWRITE(sc
, OHCI_PREQUPPER
, 0x10000);
1984 /* Set ATRetries register */
1985 OWRITE(sc
, OHCI_ATRETRY
, 1<<(13+16) | 0xfff);
1988 * Checking whether the node is root or not. If root, turn on
1991 node_id
= OREAD(sc
, FWOHCI_NODEID
);
1992 plen
= OREAD(sc
, OHCI_SID_CNT
);
1994 fc
->nodeid
= node_id
& 0x3f;
1995 fw_printf(fc
->dev
, "node_id=0x%08x, gen=%d, ",
1996 node_id
, (plen
>> 16) & 0xff);
1997 if (!(node_id
& OHCI_NODE_VALID
)) {
1998 aprint_error("Bus reset failure\n");
2004 OWRITE(sc
, FWOHCI_INTMASK
, OHCI_INT_CYC_LOST
);
2005 if ((node_id
& OHCI_NODE_ROOT
) && !nocyclemaster
) {
2006 aprint_normal("CYCLEMASTER mode\n");
2007 OWRITE(sc
, OHCI_LNKCTL
,
2008 OHCI_CNTL_CYCMTR
| OHCI_CNTL_CYCTIMER
);
2010 aprint_normal("non CYCLEMASTER mode\n");
2011 OWRITE(sc
, OHCI_LNKCTLCLR
, OHCI_CNTL_CYCMTR
);
2012 OWRITE(sc
, OHCI_LNKCTL
, OHCI_CNTL_CYCTIMER
);
2015 fc
->status
= FWBUSINIT
;
2018 fw_taskqueue_enqueue(sc
->fc
.taskqueue
,
2019 &sc
->fwohci_task_sid
);
2022 if ((stat
& ~(OHCI_INT_PHY_BUS_R
| OHCI_INT_PHY_SID
)) && (!kdb_active
))
2023 fw_taskqueue_enqueue(sc
->fc
.taskqueue
, &sc
->fwohci_task_dma
);
2025 CTR0(KTR_DEV
, "fwohci_intr_core done");
2029 fwohci_intr_dma(struct fwohci_softc
*sc
, uint32_t stat
, int count
)
2031 uint32_t irstat
, itstat
;
2033 struct firewire_comm
*fc
= (struct firewire_comm
*)sc
;
2035 CTR0(KTR_DEV
, "fwohci_intr_dma");
2036 if (stat
& OHCI_INT_DMA_IR
) {
2037 irstat
= fw_atomic_readandclear_int(&sc
->irstat
);
2038 for(i
= 0; i
< fc
->nisodma
; i
++){
2039 struct fwohci_dbch
*dbch
;
2041 if((irstat
& (1 << i
)) != 0){
2043 if ((dbch
->xferq
.flag
& FWXFERQ_OPEN
) == 0) {
2044 fw_printf(sc
->fc
.dev
,
2045 "dma(%d) not active\n", i
);
2048 fwohci_rbuf_update(sc
, i
);
2052 if (stat
& OHCI_INT_DMA_IT
) {
2053 itstat
= fw_atomic_readandclear_int(&sc
->itstat
);
2054 for(i
= 0; i
< fc
->nisodma
; i
++){
2055 if((itstat
& (1 << i
)) != 0){
2056 fwohci_tbuf_update(sc
, i
);
2060 if (stat
& OHCI_INT_DMA_PRRS
) {
2062 dump_dma(sc
, ARRS_CH
);
2063 dump_db(sc
, ARRS_CH
);
2065 fwohci_arcv(sc
, &sc
->arrs
, count
);
2067 if (stat
& OHCI_INT_DMA_PRRQ
) {
2069 dump_dma(sc
, ARRQ_CH
);
2070 dump_db(sc
, ARRQ_CH
);
2072 fwohci_arcv(sc
, &sc
->arrq
, count
);
2074 if (stat
& OHCI_INT_CYC_LOST
) {
2075 if (sc
->cycle_lost
>= 0)
2077 if (sc
->cycle_lost
> 10) {
2078 sc
->cycle_lost
= -1;
2080 OWRITE(sc
, OHCI_LNKCTLCLR
, OHCI_CNTL_CYCTIMER
);
2082 OWRITE(sc
, FWOHCI_INTMASKCLR
, OHCI_INT_CYC_LOST
);
2083 fw_printf(fc
->dev
, "too many cycle lost, "
2084 "no cycle master presents?\n");
2087 if (stat
& OHCI_INT_DMA_ATRQ
) {
2088 fwohci_txd(sc
, &(sc
->atrq
));
2090 if (stat
& OHCI_INT_DMA_ATRS
) {
2091 fwohci_txd(sc
, &(sc
->atrs
));
2093 if (stat
& OHCI_INT_PW_ERR
) {
2094 fw_printf(fc
->dev
, "posted write error\n");
2096 if (stat
& OHCI_INT_ERR
) {
2097 fw_printf(fc
->dev
, "unrecoverable error\n");
2099 if (stat
& OHCI_INT_PHY_INT
) {
2100 fw_printf(fc
->dev
, "phy int\n");
2103 CTR0(KTR_DEV
, "fwohci_intr_dma done");
2108 fwohci_task_busreset(void *arg
, int pending
)
2110 struct fwohci_softc
*sc
= (struct fwohci_softc
*)arg
;
2112 fw_busreset(&sc
->fc
, FWBUSRESET
);
2113 OWRITE(sc
, OHCI_CROMHDR
, ntohl(sc
->fc
.config_rom
[0]));
2114 OWRITE(sc
, OHCI_BUS_OPT
, ntohl(sc
->fc
.config_rom
[2]));
2118 fwohci_task_sid(void *arg
, int pending
)
2120 struct fwohci_softc
*sc
= (struct fwohci_softc
*)arg
;
2121 struct firewire_comm
*fc
= &sc
->fc
;
2125 plen
= OREAD(sc
, OHCI_SID_CNT
);
2127 if (plen
& OHCI_SID_ERR
) {
2128 fw_printf(fc
->dev
, "SID Error\n");
2131 plen
&= OHCI_SID_CNT_MASK
;
2132 if (plen
< 4 || plen
> OHCI_SIDSIZE
) {
2133 fw_printf(fc
->dev
, "invalid SID len = %d\n", plen
);
2136 plen
-= 4; /* chop control info */
2137 buf
= (uint32_t *)malloc(OHCI_SIDSIZE
, M_FW
, M_NOWAIT
);
2139 fw_printf(fc
->dev
, "malloc failed\n");
2142 for (i
= 0; i
< plen
/ 4; i
++)
2143 buf
[i
] = FWOHCI_DMA_READ(sc
->sid_buf
[i
+1]);
2144 #if 1 /* XXX needed?? */
2145 /* pending all pre-bus_reset packets */
2146 fwohci_txd(sc
, &sc
->atrq
);
2147 fwohci_txd(sc
, &sc
->atrs
);
2148 fwohci_arcv(sc
, &sc
->arrs
, -1);
2149 fwohci_arcv(sc
, &sc
->arrq
, -1);
2152 fw_sidrcv(fc
, buf
, plen
);
2157 fwohci_task_dma(void *arg
, int pending
)
2159 struct fwohci_softc
*sc
= (struct fwohci_softc
*)arg
;
2163 stat
= fw_atomic_readandclear_int(&sc
->intstat
);
2165 fwohci_intr_dma(sc
, stat
, -1);
2172 fwohci_check_stat(struct fwohci_softc
*sc
)
2174 uint32_t stat
, irstat
, itstat
;
2176 stat
= OREAD(sc
, FWOHCI_INTSTAT
);
2177 CTR1(KTR_DEV
, "fwoch_check_stat 0x%08x", stat
);
2178 if (stat
== 0xffffffff) {
2179 fw_printf(sc
->fc
.dev
,
2180 "device physically ejected?\n");
2181 return (FILTER_STRAY
);
2184 OWRITE(sc
, FWOHCI_INTSTATCLR
, stat
& ~OHCI_INT_PHY_BUS_R
);
2186 stat
&= sc
->intmask
;
2188 return (FILTER_STRAY
);
2190 fw_atomic_set_int(&sc
->intstat
, stat
);
2191 if (stat
& OHCI_INT_DMA_IR
) {
2192 irstat
= OREAD(sc
, OHCI_IR_STAT
);
2193 OWRITE(sc
, OHCI_IR_STATCLR
, irstat
);
2194 fw_atomic_set_int(&sc
->irstat
, irstat
);
2196 if (stat
& OHCI_INT_DMA_IT
) {
2197 itstat
= OREAD(sc
, OHCI_IT_STAT
);
2198 OWRITE(sc
, OHCI_IT_STATCLR
, itstat
);
2199 fw_atomic_set_int(&sc
->itstat
, itstat
);
2202 fwohci_intr_core(sc
, stat
, -1);
2203 return (FILTER_HANDLED
);
2207 fwohci_filt(void *arg
)
2209 struct fwohci_softc
*sc
= (struct fwohci_softc
*)arg
;
2211 #if defined(__NetBSD__)
2212 if (!device_is_active(sc
->fc
.dev
))
2213 return (FILTER_STRAY
);
2216 if (!(sc
->intmask
& OHCI_INT_EN
)) {
2218 return (FILTER_STRAY
);
2220 return (fwohci_check_stat(sc
));
2224 fwohci_intr(void *arg
)
2228 CTR0(KTR_DEV
, "fwohci_intr end");
2232 fwohci_poll(struct firewire_comm
*fc
, int quick
, int count
)
2234 struct fwohci_softc
*sc
= (struct fwohci_softc
*)fc
;
2236 fwohci_check_stat(sc
);
2240 fwohci_set_intr(struct firewire_comm
*fc
, int enable
)
2242 struct fwohci_softc
*sc
;
2244 sc
= (struct fwohci_softc
*)fc
;
2246 fw_printf(sc
->fc
.dev
, "fwohci_set_intr: %d\n", enable
);
2248 sc
->intmask
|= OHCI_INT_EN
;
2249 OWRITE(sc
, FWOHCI_INTMASK
, OHCI_INT_EN
);
2251 sc
->intmask
&= ~OHCI_INT_EN
;
2252 OWRITE(sc
, FWOHCI_INTMASKCLR
, OHCI_INT_EN
);
2257 fwohci_tbuf_update(struct fwohci_softc
*sc
, int dmach
)
2259 struct firewire_comm
*fc
= &sc
->fc
;
2260 struct fwohcidb
*db
;
2261 struct fw_bulkxfer
*chunk
;
2262 struct fw_xferq
*it
;
2263 uint32_t stat
, count
;
2267 ldesc
= sc
->it
[dmach
].ndesc
- 1;
2268 s
= splfw(); /* unnecessary ? */
2270 fwdma_sync_multiseg_all(sc
->it
[dmach
].am
, BUS_DMASYNC_POSTREAD
);
2272 dump_db(sc
, ITX_CH
+ dmach
);
2273 while ((chunk
= STAILQ_FIRST(&it
->stdma
)) != NULL
) {
2274 db
= ((struct fwohcidb_tr
*)(chunk
->end
))->db
;
2275 stat
= FWOHCI_DMA_READ(db
[ldesc
].db
.desc
.res
)
2276 >> OHCI_STATUS_SHIFT
;
2277 db
= ((struct fwohcidb_tr
*)(chunk
->start
))->db
;
2279 count
= FWOHCI_DMA_READ(db
[ldesc
].db
.desc
.res
)
2283 STAILQ_REMOVE_HEAD(&it
->stdma
, link
);
2284 switch (stat
& FWOHCIEV_MASK
){
2285 case FWOHCIEV_ACKCOMPL
:
2287 fw_printf(fc
->dev
, "0x%08x\n", count
);
2292 "Isochronous transmit err %02x(%s)\n",
2293 stat
, fwohcicode
[stat
& 0x1f]);
2295 STAILQ_INSERT_TAIL(&it
->stfree
, chunk
, link
);
2305 fwohci_rbuf_update(struct fwohci_softc
*sc
, int dmach
)
2307 struct firewire_comm
*fc
= &sc
->fc
;
2308 struct fwohcidb_tr
*db_tr
;
2309 struct fw_bulkxfer
*chunk
;
2310 struct fw_xferq
*ir
;
2312 int s
, w
= 0, ldesc
;
2315 ldesc
= sc
->ir
[dmach
].ndesc
- 1;
2321 if ((ir
->flag
& FWXFERQ_HANDLER
) == 0)
2323 fwdma_sync_multiseg_all(sc
->ir
[dmach
].am
, BUS_DMASYNC_POSTREAD
);
2324 while ((chunk
= STAILQ_FIRST(&ir
->stdma
)) != NULL
) {
2325 db_tr
= (struct fwohcidb_tr
*)chunk
->end
;
2326 stat
= FWOHCI_DMA_READ(db_tr
->db
[ldesc
].db
.desc
.res
)
2327 >> OHCI_STATUS_SHIFT
;
2331 if (chunk
->mbuf
!= NULL
) {
2332 fw_bus_dmamap_sync(sc
->ir
[dmach
].dmat
, db_tr
->dma_map
,
2333 BUS_DMASYNC_POSTREAD
);
2334 fw_bus_dmamap_unload(
2335 sc
->ir
[dmach
].dmat
, db_tr
->dma_map
);
2336 } else if (ir
->buf
!= NULL
) {
2337 fwdma_sync_multiseg(ir
->buf
, chunk
->poffset
,
2338 ir
->bnpacket
, BUS_DMASYNC_POSTREAD
);
2341 printf("fwohci_rbuf_update: this shouldn't happend\n");
2344 STAILQ_REMOVE_HEAD(&ir
->stdma
, link
);
2345 STAILQ_INSERT_TAIL(&ir
->stvalid
, chunk
, link
);
2346 switch (stat
& FWOHCIEV_MASK
) {
2347 case FWOHCIEV_ACKCOMPL
:
2351 chunk
->resp
= EINVAL
;
2352 fw_printf(fc
->dev
, "Isochronous receive err %02x(%s)\n",
2353 stat
, fwohcicode
[stat
& 0x1f]);
2357 if ((ir
->flag
& FWXFERQ_HANDLER
) == 0)
2362 if (ir
->flag
& FWXFERQ_HANDLER
)
2369 dump_dma(struct fwohci_softc
*sc
, uint32_t ch
)
2371 uint32_t off
, cntl
, stat
, cmd
, match
;
2381 }else if(ch
< IRX_CH
){
2382 off
= OHCI_ITCTL(ch
- ITX_CH
);
2384 off
= OHCI_IRCTL(ch
- IRX_CH
);
2386 cntl
= stat
= OREAD(sc
, off
);
2387 cmd
= OREAD(sc
, off
+ 0xc);
2388 match
= OREAD(sc
, off
+ 0x10);
2390 fw_printf(sc
->fc
.dev
, "ch %1x cntl:0x%08x cmd:0x%08x match:0x%08x\n",
2397 fw_printf(sc
->fc
.dev
, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
2399 stat
& OHCI_CNTL_DMA_RUN
? "RUN," : "",
2400 stat
& OHCI_CNTL_DMA_WAKE
? "WAKE," : "",
2401 stat
& OHCI_CNTL_DMA_DEAD
? "DEAD," : "",
2402 stat
& OHCI_CNTL_DMA_ACTIVE
? "ACTIVE," : "",
2403 stat
& OHCI_CNTL_DMA_BT
? "BRANCH," : "",
2404 stat
& OHCI_CNTL_DMA_BAD
? "BADDMA," : "",
2405 fwohcicode
[stat
& 0x1f],
2409 fw_printf(sc
->fc
.dev
, "dma %d ch: Nostat\n", ch
);
2414 dump_db(struct fwohci_softc
*sc
, uint32_t ch
)
2416 struct fwohci_dbch
*dbch
;
2417 struct fwohcidb_tr
*cp
= NULL
, *pp
, *np
= NULL
;
2418 struct fwohcidb
*curr
= NULL
, *prev
, *next
= NULL
;
2433 }else if(ch
< IRX_CH
){
2434 off
= OHCI_ITCTL(ch
- ITX_CH
);
2435 dbch
= &sc
->it
[ch
- ITX_CH
];
2437 off
= OHCI_IRCTL(ch
- IRX_CH
);
2438 dbch
= &sc
->ir
[ch
- IRX_CH
];
2440 cmd
= OREAD(sc
, off
+ 0xc);
2442 if( dbch
->ndb
== 0 ){
2443 fw_printf(sc
->fc
.dev
, "No DB is attached ch=%d\n", ch
);
2448 for(idb
= 0 ; idb
< dbch
->ndb
; idb
++ ){
2449 cp
= STAILQ_NEXT(pp
, link
);
2454 np
= STAILQ_NEXT(cp
, link
);
2455 for(jdb
= 0 ; jdb
< dbch
->ndesc
; jdb
++ ){
2456 if ((cmd
& 0xfffffff0) == cp
->bus_addr
) {
2466 pp
= STAILQ_NEXT(pp
, link
);
2476 printf("Prev DB %d\n", ch
);
2477 print_db(pp
, prev
, ch
, dbch
->ndesc
);
2479 printf("Current DB %d\n", ch
);
2480 print_db(cp
, curr
, ch
, dbch
->ndesc
);
2482 printf("Next DB %d\n", ch
);
2483 print_db(np
, next
, ch
, dbch
->ndesc
);
2486 printf("dbdump err ch = %d cmd = 0x%08x\n", ch
, cmd
);
2492 print_db(struct fwohcidb_tr
*db_tr
, struct fwohcidb
*db
,
2493 uint32_t ch
, uint32_t hogemax
)
2500 printf("No Descriptor is found\n");
2504 printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
2516 for( i
= 0 ; i
<= hogemax
; i
++){
2517 cmd
= FWOHCI_DMA_READ(db
[i
].db
.desc
.cmd
);
2518 res
= FWOHCI_DMA_READ(db
[i
].db
.desc
.res
);
2519 key
= cmd
& OHCI_KEY_MASK
;
2520 stat
= res
>> OHCI_STATUS_SHIFT
;
2521 #if defined(__DragonFly__) || \
2522 (defined(__FreeBSD__) && __FreeBSD_version < 500000)
2523 printf("%08x %s %s %s %s %5d %08x %08x %04x:%04x",
2526 printf("%08jx %s %s %s %s %5d %08x %08x %04x:%04x",
2527 (uintmax_t)db_tr
->bus_addr
,
2529 dbcode
[(cmd
>> 28) & 0xf],
2530 dbkey
[(cmd
>> 24) & 0x7],
2531 dbcond
[(cmd
>> 20) & 0x3],
2532 dbcond
[(cmd
>> 18) & 0x3],
2533 cmd
& OHCI_COUNT_MASK
,
2534 FWOHCI_DMA_READ(db
[i
].db
.desc
.addr
),
2535 FWOHCI_DMA_READ(db
[i
].db
.desc
.depend
),
2537 res
& OHCI_COUNT_MASK
);
2539 printf(" %s%s%s%s%s%s %s(%x)\n",
2540 stat
& OHCI_CNTL_DMA_RUN
? "RUN," : "",
2541 stat
& OHCI_CNTL_DMA_WAKE
? "WAKE," : "",
2542 stat
& OHCI_CNTL_DMA_DEAD
? "DEAD," : "",
2543 stat
& OHCI_CNTL_DMA_ACTIVE
? "ACTIVE," : "",
2544 stat
& OHCI_CNTL_DMA_BT
? "BRANCH," : "",
2545 stat
& OHCI_CNTL_DMA_BAD
? "BADDMA," : "",
2546 fwohcicode
[stat
& 0x1f],
2550 printf(" Nostat\n");
2552 if(key
== OHCI_KEY_ST2
){
2553 printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
2554 FWOHCI_DMA_READ(db
[i
+1].db
.immed
[0]),
2555 FWOHCI_DMA_READ(db
[i
+1].db
.immed
[1]),
2556 FWOHCI_DMA_READ(db
[i
+1].db
.immed
[2]),
2557 FWOHCI_DMA_READ(db
[i
+1].db
.immed
[3]));
2559 if(key
== OHCI_KEY_DEVICE
){
2562 if((cmd
& OHCI_BRANCH_MASK
)
2563 == OHCI_BRANCH_ALWAYS
){
2566 if((cmd
& OHCI_CMD_MASK
)
2567 == OHCI_OUTPUT_LAST
){
2570 if((cmd
& OHCI_CMD_MASK
)
2571 == OHCI_INPUT_LAST
){
2574 if(key
== OHCI_KEY_ST2
){
2582 fwohci_ibr(struct firewire_comm
*fc
)
2584 struct fwohci_softc
*sc
;
2587 fw_printf(fc
->dev
, "Initiate bus reset\n");
2588 sc
= (struct fwohci_softc
*)fc
;
2591 * Make sure our cached values from the config rom are
2594 OWRITE(sc
, OHCI_CROMHDR
, ntohl(sc
->fc
.config_rom
[0]));
2595 OWRITE(sc
, OHCI_BUS_OPT
, ntohl(sc
->fc
.config_rom
[2]));
2598 * Set root hold-off bit so that non cyclemaster capable node
2599 * shouldn't became the root node.
2602 fun
= fwphy_rddata(sc
, FW_PHY_IBR_REG
);
2603 fun
|= FW_PHY_IBR
| FW_PHY_RHB
;
2604 fun
= fwphy_wrdata(sc
, FW_PHY_IBR_REG
, fun
);
2605 #else /* Short bus reset */
2606 fun
= fwphy_rddata(sc
, FW_PHY_ISBR_REG
);
2607 fun
|= FW_PHY_ISBR
| FW_PHY_RHB
;
2608 fun
= fwphy_wrdata(sc
, FW_PHY_ISBR_REG
, fun
);
2613 fwohci_txbufdb(struct fwohci_softc
*sc
, int dmach
, struct fw_bulkxfer
*bulkxfer
)
2615 struct fwohcidb_tr
*db_tr
, *fdb_tr
;
2616 struct fwohci_dbch
*dbch
;
2617 struct fwohcidb
*db
;
2619 struct fwohci_txpkthdr
*ohcifp
;
2620 unsigned short chtag
;
2623 FW_GLOCK_ASSERT(&sc
->fc
);
2625 dbch
= &sc
->it
[dmach
];
2626 chtag
= sc
->it
[dmach
].xferq
.flag
& 0xff;
2628 db_tr
= (struct fwohcidb_tr
*)(bulkxfer
->start
);
2629 fdb_tr
= (struct fwohcidb_tr
*)(bulkxfer
->end
);
2631 fw_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, db_tr->bus_addr, fdb_tr->bus_addr);
2633 for (idb
= 0; idb
< dbch
->xferq
.bnpacket
; idb
++) {
2635 fp
= (struct fw_pkt
*)db_tr
->buf
;
2636 ohcifp
= (struct fwohci_txpkthdr
*) db
[1].db
.immed
;
2637 ohcifp
->mode
.ld
[0] = fp
->mode
.ld
[0];
2638 ohcifp
->mode
.common
.spd
= 0 & 0x7;
2639 ohcifp
->mode
.stream
.len
= fp
->mode
.stream
.len
;
2640 ohcifp
->mode
.stream
.chtag
= chtag
;
2641 ohcifp
->mode
.stream
.tcode
= 0xa;
2642 #if BYTE_ORDER == BIG_ENDIAN
2643 FWOHCI_DMA_WRITE(db
[1].db
.immed
[0], db
[1].db
.immed
[0]);
2644 FWOHCI_DMA_WRITE(db
[1].db
.immed
[1], db
[1].db
.immed
[1]);
2647 FWOHCI_DMA_CLEAR(db
[2].db
.desc
.cmd
, OHCI_COUNT_MASK
);
2648 FWOHCI_DMA_SET(db
[2].db
.desc
.cmd
, fp
->mode
.stream
.len
);
2649 FWOHCI_DMA_WRITE(db
[2].db
.desc
.res
, 0);
2650 #if 0 /* if bulkxfer->npackets changes */
2651 db
[2].db
.desc
.cmd
= OHCI_OUTPUT_LAST
2653 | OHCI_BRANCH_ALWAYS
;
2654 db
[0].db
.desc
.depend
=
2655 = db
[dbch
->ndesc
- 1].db
.desc
.depend
2656 = STAILQ_NEXT(db_tr
, link
)->bus_addr
| dbch
->ndesc
;
2658 FWOHCI_DMA_SET(db
[0].db
.desc
.depend
, dbch
->ndesc
);
2659 FWOHCI_DMA_SET(db
[dbch
->ndesc
- 1].db
.desc
.depend
, dbch
->ndesc
);
2661 bulkxfer
->end
= (void *)db_tr
;
2662 db_tr
= STAILQ_NEXT(db_tr
, link
);
2664 db
= ((struct fwohcidb_tr
*)bulkxfer
->end
)->db
;
2665 FWOHCI_DMA_CLEAR(db
[0].db
.desc
.depend
, 0xf);
2666 FWOHCI_DMA_CLEAR(db
[dbch
->ndesc
- 1].db
.desc
.depend
, 0xf);
2667 #if 0 /* if bulkxfer->npackets changes */
2668 db
[dbch
->ndesc
- 1].db
.desc
.control
|= OHCI_INTERRUPT_ALWAYS
;
2669 /* OHCI 1.1 and above */
2670 db
[0].db
.desc
.control
|= OHCI_INTERRUPT_ALWAYS
;
2673 db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2674 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2675 fw_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, db_tr->bus_addr, fdb_tr->bus_addr);
2681 fwohci_add_tx_buf(struct fwohci_dbch
*dbch
, struct fwohcidb_tr
*db_tr
,
2684 struct fwohcidb
*db
= db_tr
->db
;
2685 struct fw_xferq
*it
;
2693 db_tr
->buf
= fwdma_v_addr(it
->buf
, poffset
);
2696 FWOHCI_DMA_WRITE(db
[0].db
.desc
.cmd
,
2697 OHCI_OUTPUT_MORE
| OHCI_KEY_ST2
| 8);
2698 FWOHCI_DMA_WRITE(db
[0].db
.desc
.addr
, 0);
2699 memset((void *)&db
[1].db
.immed
[0], 0, sizeof(db
[1].db
.immed
));
2700 FWOHCI_DMA_WRITE(db
[2].db
.desc
.addr
,
2701 fwdma_bus_addr(it
->buf
, poffset
) + sizeof(uint32_t));
2703 FWOHCI_DMA_WRITE(db
[2].db
.desc
.cmd
,
2704 OHCI_OUTPUT_LAST
| OHCI_UPDATE
| OHCI_BRANCH_ALWAYS
);
2706 FWOHCI_DMA_WRITE(db
[0].db
.desc
.res
, 0);
2707 FWOHCI_DMA_WRITE(db
[2].db
.desc
.res
, 0);
2713 fwohci_add_rx_buf(struct fwohci_dbch
*dbch
, struct fwohcidb_tr
*db_tr
,
2714 int poffset
, struct fwdma_alloc
*dummy_dma
)
2716 struct fwohcidb
*db
= db_tr
->db
;
2717 struct fw_xferq
*ir
;
2723 if (ir
->buf
== NULL
&& (dbch
->xferq
.flag
& FWXFERQ_EXTBUF
) == 0) {
2724 if (db_tr
->buf
== NULL
)
2725 db_tr
->buf
= fwdma_malloc_size(
2726 dbch
->dmat
, &db_tr
->dma_map
,
2727 ir
->psize
, &dbuf
[0], BUS_DMA_NOWAIT
);
2728 if (db_tr
->buf
== NULL
)
2731 dsiz
[0] = ir
->psize
;
2732 fw_bus_dmamap_sync(dbch
->dmat
, db_tr
->dma_map
,
2733 BUS_DMASYNC_PREREAD
);
2736 if (dummy_dma
!= NULL
) {
2737 dsiz
[db_tr
->dbcnt
] = sizeof(uint32_t);
2738 dbuf
[db_tr
->dbcnt
++] = dummy_dma
->bus_addr
;
2740 dsiz
[db_tr
->dbcnt
] = ir
->psize
;
2741 if (ir
->buf
!= NULL
) {
2742 db_tr
->buf
= fwdma_v_addr(ir
->buf
, poffset
);
2743 dbuf
[db_tr
->dbcnt
] = fwdma_bus_addr( ir
->buf
, poffset
);
2747 for(i
= 0 ; i
< db_tr
->dbcnt
; i
++){
2748 FWOHCI_DMA_WRITE(db
[i
].db
.desc
.addr
, dbuf
[i
]);
2749 FWOHCI_DMA_WRITE(db
[i
].db
.desc
.cmd
, OHCI_INPUT_MORE
| dsiz
[i
]);
2750 if (ir
->flag
& FWXFERQ_STREAM
) {
2751 FWOHCI_DMA_SET(db
[i
].db
.desc
.cmd
, OHCI_UPDATE
);
2753 FWOHCI_DMA_WRITE(db
[i
].db
.desc
.res
, dsiz
[i
]);
2755 ldesc
= db_tr
->dbcnt
- 1;
2756 if (ir
->flag
& FWXFERQ_STREAM
) {
2757 FWOHCI_DMA_SET(db
[ldesc
].db
.desc
.cmd
, OHCI_INPUT_LAST
);
2759 FWOHCI_DMA_SET(db
[ldesc
].db
.desc
.cmd
, OHCI_BRANCH_ALWAYS
);
2765 fwohci_arcv_swap(struct fw_pkt
*fp
, int len
)
2770 #if BYTE_ORDER == BIG_ENDIAN
2774 ld0
= FWOHCI_DMA_READ(fp
->mode
.ld
[0]);
2776 printf("ld0: x%08x\n", ld0
);
2778 fp0
= (struct fw_pkt
*)&ld0
;
2779 /* determine length to swap */
2780 switch (fp0
->mode
.common
.tcode
) {
2782 CTR0(KTR_DEV
, "WRES");
2786 case FWOHCITCODE_PHY
:
2797 printf("Unknown tcode %d\n", fp0
->mode
.common
.tcode
);
2800 hlen
= tinfo
[fp0
->mode
.common
.tcode
].hdr_len
;
2803 printf("splitted header\n");
2806 #if BYTE_ORDER == BIG_ENDIAN
2807 for(i
= 0; i
< slen
/4; i
++)
2808 fp
->mode
.ld
[i
] = FWOHCI_DMA_READ(fp
->mode
.ld
[i
]);
2814 fwohci_get_plen(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
, struct fw_pkt
*fp
)
2816 const struct tcode_info
*info
;
2819 info
= &tinfo
[fp
->mode
.common
.tcode
];
2820 r
= info
->hdr_len
+ sizeof(uint32_t);
2821 if ((info
->flag
& FWTI_BLOCK_ASY
) != 0)
2822 r
+= roundup2(fp
->mode
.wreqb
.len
, sizeof(uint32_t));
2824 if (r
== sizeof(uint32_t)) {
2826 fw_printf(sc
->fc
.dev
, "Unknown tcode %d\n",
2827 fp
->mode
.common
.tcode
);
2831 if (r
> dbch
->xferq
.psize
) {
2832 fw_printf(sc
->fc
.dev
, "Invalid packet length %d\n", r
);
2841 fwohci_arcv_free_buf(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
,
2842 struct fwohcidb_tr
*db_tr
, uint32_t off
, int wake
)
2844 struct fwohcidb
*db
= &db_tr
->db
[0];
2846 FWOHCI_DMA_CLEAR(db
->db
.desc
.depend
, 0xf);
2847 FWOHCI_DMA_WRITE(db
->db
.desc
.res
, dbch
->xferq
.psize
);
2848 FWOHCI_DMA_SET(dbch
->bottom
->db
[0].db
.desc
.depend
, 1);
2849 fwdma_sync_multiseg_all(dbch
->am
,
2850 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
2851 dbch
->bottom
= db_tr
;
2854 OWRITE(sc
, OHCI_DMACTL(off
), OHCI_CNTL_DMA_WAKE
);
2858 fwohci_arcv(struct fwohci_softc
*sc
, struct fwohci_dbch
*dbch
, int count
)
2860 struct fwohcidb_tr
*db_tr
;
2861 struct iovec vec
[2];
2862 struct fw_pkt pktbuf
;
2866 uint32_t stat
, off
, status
, event
;
2868 int len
, plen
, hlen
, pcnt
, offset
;
2873 CTR0(KTR_DEV
, "fwohci_arv");
2875 if(&sc
->arrq
== dbch
){
2877 }else if(&sc
->arrs
== dbch
){
2886 /* XXX we cannot handle a packet which lies in more than two buf */
2887 fwdma_sync_multiseg_all(dbch
->am
,
2888 BUS_DMASYNC_POSTREAD
| BUS_DMASYNC_POSTWRITE
);
2889 status
= FWOHCI_DMA_READ(db_tr
->db
[0].db
.desc
.res
) >> OHCI_STATUS_SHIFT
;
2890 resCount
= FWOHCI_DMA_READ(db_tr
->db
[0].db
.desc
.res
) & OHCI_COUNT_MASK
;
2891 while (status
& OHCI_CNTL_DMA_ACTIVE
) {
2894 if (off
== OHCI_ARQOFF
)
2895 printf("buf 0x%08x, status 0x%04x, resCount 0x%04x\n",
2896 db_tr
->bus_addr
, status
, resCount
);
2898 len
= dbch
->xferq
.psize
- resCount
;
2899 ld
= (uint8_t *)db_tr
->buf
;
2900 if (dbch
->pdb_tr
== NULL
) {
2901 len
-= dbch
->buf_offset
;
2902 ld
+= dbch
->buf_offset
;
2905 fw_bus_dmamap_sync(dbch
->dmat
, db_tr
->dma_map
,
2906 BUS_DMASYNC_POSTREAD
);
2908 if (count
>= 0 && count
-- == 0)
2910 if(dbch
->pdb_tr
!= NULL
){
2911 /* we have a fragment in previous buffer */
2914 offset
= dbch
->buf_offset
;
2917 buf
= (char *)dbch
->pdb_tr
->buf
+ offset
;
2918 rlen
= dbch
->xferq
.psize
- offset
;
2920 printf("rlen=%d, offset=%d\n",
2921 rlen
, dbch
->buf_offset
);
2922 if (dbch
->buf_offset
< 0) {
2923 /* splitted in header, pull up */
2926 p
= (char *)&pktbuf
;
2927 memcpy(p
, buf
, rlen
);
2929 /* this must be too long but harmless */
2930 rlen
= sizeof(pktbuf
) - rlen
;
2932 printf("why rlen < 0\n");
2933 memcpy(p
, db_tr
->buf
, rlen
);
2936 hlen
= fwohci_arcv_swap(&pktbuf
, sizeof(pktbuf
));
2938 printf("hlen should be positive.");
2941 offset
= sizeof(pktbuf
);
2942 vec
[0].iov_base
= (char *)&pktbuf
;
2943 vec
[0].iov_len
= offset
;
2945 /* splitted in payload */
2947 vec
[0].iov_base
= buf
;
2948 vec
[0].iov_len
= rlen
;
2950 fp
=(struct fw_pkt
*)vec
[0].iov_base
;
2953 /* no fragment in previous buffer */
2954 fp
=(struct fw_pkt
*)ld
;
2955 hlen
= fwohci_arcv_swap(fp
, len
);
2959 dbch
->pdb_tr
= db_tr
;
2960 dbch
->buf_offset
= - dbch
->buf_offset
;
2962 if (resCount
!= 0) {
2963 printf("resCount=%d hlen=%d\n",
2972 plen
= fwohci_get_plen(sc
, dbch
, fp
) - offset
;
2974 /* minimum header size + trailer
2975 = sizeof(fw_pkt) so this shouldn't happens */
2976 printf("plen(%d) is negative! offset=%d\n",
2983 dbch
->pdb_tr
= db_tr
;
2985 printf("splitted payload\n");
2987 if (resCount
!= 0) {
2988 printf("resCount=%d plen=%d"
2990 resCount
, plen
, len
);
2995 vec
[nvec
].iov_base
= ld
;
2996 vec
[nvec
].iov_len
= plen
;
3000 dbch
->buf_offset
= ld
- (uint8_t *)db_tr
->buf
;
3002 printf("nvec == 0\n");
3004 /* DMA result-code will be written at the tail of packet */
3005 stat
= FWOHCI_DMA_READ(*(uint32_t *)(ld
- sizeof(struct fwohci_trailer
)));
3007 printf("plen: %d, stat %x\n",
3010 spd
= (stat
>> 21) & 0x3;
3011 event
= (stat
>> 16) & 0x1f;
3013 case FWOHCIEV_ACKPEND
:
3015 printf("fwohci_arcv: ack pending tcode=0x%x..\n", fp
->mode
.common
.tcode
);
3018 case FWOHCIEV_ACKCOMPL
:
3020 struct fw_rcv_buf rb
;
3022 if ((vec
[nvec
-1].iov_len
-=
3023 sizeof(struct fwohci_trailer
)) == 0)
3032 case FWOHCIEV_BUSRST
:
3033 if ((sc
->fc
.status
!= FWBUSRESET
) &&
3034 (sc
->fc
.status
!= FWBUSINIT
))
3035 printf("got BUSRST packet!?\n");
3038 fw_printf(sc
->fc
.dev
,
3039 "Async DMA Receive error err=%02x %s"
3040 " plen=%d offset=%d len=%d status=0x%08x"
3041 " tcode=0x%x, stat=0x%08x\n",
3042 event
, fwohcicode
[event
], plen
,
3043 dbch
->buf_offset
, len
,
3044 OREAD(sc
, OHCI_DMACTL(off
)),
3045 fp
->mode
.common
.tcode
, stat
);
3052 if (dbch
->pdb_tr
!= NULL
) {
3053 fwohci_arcv_free_buf(sc
, dbch
, dbch
->pdb_tr
,
3055 dbch
->pdb_tr
= NULL
;
3060 if (resCount
== 0) {
3061 /* done on this buffer */
3062 if (dbch
->pdb_tr
== NULL
) {
3063 fwohci_arcv_free_buf(sc
, dbch
, db_tr
, off
, 1);
3064 dbch
->buf_offset
= 0;
3066 if (dbch
->pdb_tr
!= db_tr
)
3067 printf("pdb_tr != db_tr\n");
3068 db_tr
= STAILQ_NEXT(db_tr
, link
);
3069 fwdma_sync_multiseg_all(dbch
->am
,
3070 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
3071 status
= FWOHCI_DMA_READ(db_tr
->db
[0].db
.desc
.res
)
3072 >> OHCI_STATUS_SHIFT
;
3073 resCount
= FWOHCI_DMA_READ(db_tr
->db
[0].db
.desc
.res
)
3075 /* XXX check buffer overrun */
3078 dbch
->buf_offset
= dbch
->xferq
.psize
- resCount
;
3080 dbch
->dmat
, db_tr
->dma_map
, BUS_DMASYNC_PREREAD
);
3083 /* XXX make sure DMA is not dead */
3087 printf("fwohci_arcv: no packets\n");
3089 fwdma_sync_multiseg_all(dbch
->am
,
3090 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
3095 fw_printf(sc
->fc
.dev
, "AR DMA status=%x, ",
3096 OREAD(sc
, OHCI_DMACTL(off
)));
3097 dbch
->pdb_tr
= NULL
;
3098 /* skip until resCount != 0 */
3099 printf(" skip buffer");
3100 while (resCount
== 0) {
3102 fwohci_arcv_free_buf(sc
, dbch
, db_tr
, off
, 0);
3103 db_tr
= STAILQ_NEXT(db_tr
, link
);
3104 resCount
= FWOHCI_DMA_READ(db_tr
->db
[0].db
.desc
.res
)
3109 dbch
->buf_offset
= dbch
->xferq
.psize
- resCount
;
3110 OWRITE(sc
, OHCI_DMACTL(off
), OHCI_CNTL_DMA_WAKE
);
3111 fwdma_sync_multiseg_all(
3112 dbch
->am
, BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
3113 fw_bus_dmamap_sync(dbch
->dmat
, db_tr
->dma_map
, BUS_DMASYNC_PREREAD
);
3116 #if defined(__NetBSD__)
3119 fwohci_print(void *aux
, const char *pnp
)
3121 struct fw_attach_args
*fwa
= (struct fw_attach_args
*)aux
;
3124 aprint_normal("%s at %s", fwa
->name
, pnp
);