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