Deleted Added
full compact
fwohci.c (106802) fwohci.c (107653)
1/*
2 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the acknowledgement as bellow:
15 *
16 * This product includes software developed by K. Kobayashi and H. Shimokawa
17 *
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
1/*
2 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the acknowledgement as bellow:
15 *
16 * This product includes software developed by K. Kobayashi and H. Shimokawa
17 *
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * $FreeBSD: head/sys/dev/firewire/fwohci.c 106802 2002-11-12 10:02:50Z simokawa $
33 * $FreeBSD: head/sys/dev/firewire/fwohci.c 107653 2002-12-06 02:17:30Z simokawa $
34 *
35 */
36
37#define ATRQ_CH 0
38#define ATRS_CH 1
39#define ARRQ_CH 2
40#define ARRS_CH 3
41#define ITX_CH 4
42#define IRX_CH 0x24
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/types.h>
47#include <sys/mbuf.h>
48#include <sys/mman.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/signalvar.h>
52#include <sys/malloc.h>
53#include <sys/uio.h>
54#include <sys/sockio.h>
55#include <sys/bus.h>
56#include <sys/kernel.h>
57#include <sys/conf.h>
58
59#include <machine/bus.h>
60#include <machine/resource.h>
61#include <sys/rman.h>
62
63#include <machine/cpufunc.h> /* for rdtsc proto for clock.h below */
64#include <machine/clock.h>
65#include <pci/pcivar.h>
66#include <pci/pcireg.h>
67#include <vm/vm.h>
68#include <vm/vm_extern.h>
69#include <vm/pmap.h> /* for vtophys proto */
70
71#include <dev/firewire/firewire.h>
72#include <dev/firewire/firewirebusreg.h>
73#include <dev/firewire/firewirereg.h>
74#include <dev/firewire/fwohcireg.h>
75#include <dev/firewire/fwohcivar.h>
76#include <dev/firewire/firewire_phy.h>
77
78#undef OHCI_DEBUG
79
80static char dbcode[16][0x10]={"OUTM", "OUTL","INPM","INPL",
81 "STOR","LOAD","NOP ","STOP",};
82static char dbkey[8][0x10]={"ST0", "ST1","ST2","ST3",
83 "UNDEF","REG","SYS","DEV"};
84char fwohcicode[32][0x20]={
85 "No stat","Undef","long","miss Ack err",
86 "underrun","overrun","desc err", "data read err",
87 "data write err","bus reset","timeout","tcode err",
88 "Undef","Undef","unknown event","flushed",
89 "Undef","ack complete","ack pend","Undef",
90 "ack busy_X","ack busy_A","ack busy_B","Undef",
91 "Undef","Undef","Undef","ack tardy",
92 "Undef","ack data_err","ack type_err",""};
93#define MAX_SPEED 2
94extern char linkspeed[MAX_SPEED+1][0x10];
95extern int maxrec[MAX_SPEED+1];
96static char dbcond[4][0x10]={"NEV","C=1", "C=0", "ALL"};
97u_int32_t tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31};
98
99static struct tcode_info tinfo[] = {
100/* hdr_len block flag*/
101/* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL},
102/* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY},
103/* 2 WRES */ {12, FWTI_RES},
104/* 3 XXX */ { 0, 0},
105/* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL},
106/* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL},
107/* 6 RRESQ */ {16, FWTI_RES},
108/* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY},
109/* 8 CYCS */ { 0, 0},
110/* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY},
111/* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR},
112/* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY},
113/* c XXX */ { 0, 0},
114/* d XXX */ { 0, 0},
115/* e PHY */ {12, FWTI_REQ},
116/* f XXX */ { 0, 0}
117};
118
119#define OHCI_WRITE_SIGMASK 0xffff0000
120#define OHCI_READ_SIGMASK 0xffff0000
121
122#define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
123#define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r))
124
125static void fwohci_ibr __P((struct firewire_comm *));
126static void fwohci_db_init __P((struct fwohci_dbch *));
127static void fwohci_db_free __P((struct fwohci_dbch *));
128static void fwohci_arcv __P((struct fwohci_softc *, struct fwohci_dbch *, int));
129static void fwohci_ircv __P((struct fwohci_softc *, struct fwohci_dbch *, int));
130static void fwohci_txd __P((struct fwohci_softc *, struct fwohci_dbch *));
131static void fwohci_start_atq __P((struct firewire_comm *));
132static void fwohci_start_ats __P((struct firewire_comm *));
133static void fwohci_start __P((struct fwohci_softc *, struct fwohci_dbch *));
134static void fwohci_drain_atq __P((struct firewire_comm *, struct fw_xfer *));
135static void fwohci_drain_ats __P((struct firewire_comm *, struct fw_xfer *));
136static void fwohci_drain __P((struct firewire_comm *, struct fw_xfer *, struct fwohci_dbch *));
137static u_int32_t fwphy_wrdata __P(( struct fwohci_softc *, u_int32_t, u_int32_t));
138static u_int32_t fwphy_rddata __P(( struct fwohci_softc *, u_int32_t));
139static int fwohci_rx_enable __P((struct fwohci_softc *, struct fwohci_dbch *));
140static int fwohci_tx_enable __P((struct fwohci_softc *, struct fwohci_dbch *));
141static int fwohci_irx_enable __P((struct firewire_comm *, int));
142static int fwohci_irxpp_enable __P((struct firewire_comm *, int));
143static int fwohci_irxbuf_enable __P((struct firewire_comm *, int));
144static int fwohci_irx_disable __P((struct firewire_comm *, int));
145static void fwohci_irx_post __P((struct firewire_comm *, u_int32_t *));
146static int fwohci_itxbuf_enable __P((struct firewire_comm *, int));
147static int fwohci_itx_disable __P((struct firewire_comm *, int));
148static void fwohci_timeout __P((void *));
149static void fwohci_poll __P((struct firewire_comm *, int, int));
150static void fwohci_set_intr __P((struct firewire_comm *, int));
151static int fwohci_add_rx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *, void *));
152static int fwohci_add_tx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *));
153static void dump_db __P((struct fwohci_softc *, u_int32_t));
154static void print_db __P((volatile struct fwohcidb *, u_int32_t , u_int32_t));
155static void dump_dma __P((struct fwohci_softc *, u_int32_t));
156static u_int32_t fwohci_cyctimer __P((struct firewire_comm *));
157static void fwohci_rbuf_update __P((struct fwohci_softc *, int));
158static void fwohci_tbuf_update __P((struct fwohci_softc *, int));
159void fwohci_txbufdb __P((struct fwohci_softc *, int , struct fw_bulkxfer *));
160
161/*
162 * memory allocated for DMA programs
163 */
164#define DMA_PROG_ALLOC (8 * PAGE_SIZE)
165
166/* #define NDB 1024 */
167#define NDB FWMAXQUEUE
168#define NDVDB (DVBUF * NDB)
169
170#define OHCI_VERSION 0x00
171#define OHCI_CROMHDR 0x18
172#define OHCI_BUS_OPT 0x20
173#define OHCI_BUSIRMC (1 << 31)
174#define OHCI_BUSCMC (1 << 30)
175#define OHCI_BUSISC (1 << 29)
176#define OHCI_BUSBMC (1 << 28)
177#define OHCI_BUSPMC (1 << 27)
178#define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\
179 OHCI_BUSBMC | OHCI_BUSPMC
180
181#define OHCI_EUID_HI 0x24
182#define OHCI_EUID_LO 0x28
183
184#define OHCI_CROMPTR 0x34
185#define OHCI_HCCCTL 0x50
186#define OHCI_HCCCTLCLR 0x54
187#define OHCI_AREQHI 0x100
188#define OHCI_AREQHICLR 0x104
189#define OHCI_AREQLO 0x108
190#define OHCI_AREQLOCLR 0x10c
191#define OHCI_PREQHI 0x110
192#define OHCI_PREQHICLR 0x114
193#define OHCI_PREQLO 0x118
194#define OHCI_PREQLOCLR 0x11c
195#define OHCI_PREQUPPER 0x120
196
197#define OHCI_SID_BUF 0x64
198#define OHCI_SID_CNT 0x68
199#define OHCI_SID_CNT_MASK 0xffc
200
201#define OHCI_IT_STAT 0x90
202#define OHCI_IT_STATCLR 0x94
203#define OHCI_IT_MASK 0x98
204#define OHCI_IT_MASKCLR 0x9c
205
206#define OHCI_IR_STAT 0xa0
207#define OHCI_IR_STATCLR 0xa4
208#define OHCI_IR_MASK 0xa8
209#define OHCI_IR_MASKCLR 0xac
210
211#define OHCI_LNKCTL 0xe0
212#define OHCI_LNKCTLCLR 0xe4
213
214#define OHCI_PHYACCESS 0xec
215#define OHCI_CYCLETIMER 0xf0
216
217#define OHCI_DMACTL(off) (off)
218#define OHCI_DMACTLCLR(off) (off + 4)
219#define OHCI_DMACMD(off) (off + 0xc)
220#define OHCI_DMAMATCH(off) (off + 0x10)
221
222#define OHCI_ATQOFF 0x180
223#define OHCI_ATQCTL OHCI_ATQOFF
224#define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4)
225#define OHCI_ATQCMD (OHCI_ATQOFF + 0xc)
226#define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10)
227
228#define OHCI_ATSOFF 0x1a0
229#define OHCI_ATSCTL OHCI_ATSOFF
230#define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4)
231#define OHCI_ATSCMD (OHCI_ATSOFF + 0xc)
232#define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10)
233
234#define OHCI_ARQOFF 0x1c0
235#define OHCI_ARQCTL OHCI_ARQOFF
236#define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4)
237#define OHCI_ARQCMD (OHCI_ARQOFF + 0xc)
238#define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10)
239
240#define OHCI_ARSOFF 0x1e0
241#define OHCI_ARSCTL OHCI_ARSOFF
242#define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4)
243#define OHCI_ARSCMD (OHCI_ARSOFF + 0xc)
244#define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10)
245
246#define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH))
247#define OHCI_ITCTL(CH) (OHCI_ITOFF(CH))
248#define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4)
249#define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc)
250
251#define OHCI_IROFF(CH) (0x400 + 0x20 * (CH))
252#define OHCI_IRCTL(CH) (OHCI_IROFF(CH))
253#define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4)
254#define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc)
255#define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10)
256
257d_ioctl_t fwohci_ioctl;
258
259/*
260 * Communication with PHY device
261 */
262static u_int32_t
263fwphy_wrdata( struct fwohci_softc *sc, u_int32_t addr, u_int32_t data)
264{
265 u_int32_t fun;
266
267 addr &= 0xf;
268 data &= 0xff;
269
270 fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA));
271 OWRITE(sc, OHCI_PHYACCESS, fun);
272 DELAY(100);
273
274 return(fwphy_rddata( sc, addr));
275}
276
277static u_int32_t
278fwohci_set_bus_manager(struct firewire_comm *fc, u_int node)
279{
280 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
281 int i;
282 u_int32_t bm;
283
284#define OHCI_CSR_DATA 0x0c
285#define OHCI_CSR_COMP 0x10
286#define OHCI_CSR_CONT 0x14
287#define OHCI_BUS_MANAGER_ID 0
288
289 OWRITE(sc, OHCI_CSR_DATA, node);
290 OWRITE(sc, OHCI_CSR_COMP, 0x3f);
291 OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID);
292 for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++)
293 DELAY(100);
294 bm = OREAD(sc, OHCI_CSR_DATA);
34 *
35 */
36
37#define ATRQ_CH 0
38#define ATRS_CH 1
39#define ARRQ_CH 2
40#define ARRS_CH 3
41#define ITX_CH 4
42#define IRX_CH 0x24
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/types.h>
47#include <sys/mbuf.h>
48#include <sys/mman.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/signalvar.h>
52#include <sys/malloc.h>
53#include <sys/uio.h>
54#include <sys/sockio.h>
55#include <sys/bus.h>
56#include <sys/kernel.h>
57#include <sys/conf.h>
58
59#include <machine/bus.h>
60#include <machine/resource.h>
61#include <sys/rman.h>
62
63#include <machine/cpufunc.h> /* for rdtsc proto for clock.h below */
64#include <machine/clock.h>
65#include <pci/pcivar.h>
66#include <pci/pcireg.h>
67#include <vm/vm.h>
68#include <vm/vm_extern.h>
69#include <vm/pmap.h> /* for vtophys proto */
70
71#include <dev/firewire/firewire.h>
72#include <dev/firewire/firewirebusreg.h>
73#include <dev/firewire/firewirereg.h>
74#include <dev/firewire/fwohcireg.h>
75#include <dev/firewire/fwohcivar.h>
76#include <dev/firewire/firewire_phy.h>
77
78#undef OHCI_DEBUG
79
80static char dbcode[16][0x10]={"OUTM", "OUTL","INPM","INPL",
81 "STOR","LOAD","NOP ","STOP",};
82static char dbkey[8][0x10]={"ST0", "ST1","ST2","ST3",
83 "UNDEF","REG","SYS","DEV"};
84char fwohcicode[32][0x20]={
85 "No stat","Undef","long","miss Ack err",
86 "underrun","overrun","desc err", "data read err",
87 "data write err","bus reset","timeout","tcode err",
88 "Undef","Undef","unknown event","flushed",
89 "Undef","ack complete","ack pend","Undef",
90 "ack busy_X","ack busy_A","ack busy_B","Undef",
91 "Undef","Undef","Undef","ack tardy",
92 "Undef","ack data_err","ack type_err",""};
93#define MAX_SPEED 2
94extern char linkspeed[MAX_SPEED+1][0x10];
95extern int maxrec[MAX_SPEED+1];
96static char dbcond[4][0x10]={"NEV","C=1", "C=0", "ALL"};
97u_int32_t tagbit[4] = { 1 << 28, 1 << 29, 1 << 30, 1 << 31};
98
99static struct tcode_info tinfo[] = {
100/* hdr_len block flag*/
101/* 0 WREQQ */ {16, FWTI_REQ | FWTI_TLABEL},
102/* 1 WREQB */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY},
103/* 2 WRES */ {12, FWTI_RES},
104/* 3 XXX */ { 0, 0},
105/* 4 RREQQ */ {12, FWTI_REQ | FWTI_TLABEL},
106/* 5 RREQB */ {16, FWTI_REQ | FWTI_TLABEL},
107/* 6 RRESQ */ {16, FWTI_RES},
108/* 7 RRESB */ {16, FWTI_RES | FWTI_BLOCK_ASY},
109/* 8 CYCS */ { 0, 0},
110/* 9 LREQ */ {16, FWTI_REQ | FWTI_TLABEL | FWTI_BLOCK_ASY},
111/* a STREAM */ { 4, FWTI_REQ | FWTI_BLOCK_STR},
112/* b LRES */ {16, FWTI_RES | FWTI_BLOCK_ASY},
113/* c XXX */ { 0, 0},
114/* d XXX */ { 0, 0},
115/* e PHY */ {12, FWTI_REQ},
116/* f XXX */ { 0, 0}
117};
118
119#define OHCI_WRITE_SIGMASK 0xffff0000
120#define OHCI_READ_SIGMASK 0xffff0000
121
122#define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
123#define OREAD(sc, r) bus_space_read_4((sc)->bst, (sc)->bsh, (r))
124
125static void fwohci_ibr __P((struct firewire_comm *));
126static void fwohci_db_init __P((struct fwohci_dbch *));
127static void fwohci_db_free __P((struct fwohci_dbch *));
128static void fwohci_arcv __P((struct fwohci_softc *, struct fwohci_dbch *, int));
129static void fwohci_ircv __P((struct fwohci_softc *, struct fwohci_dbch *, int));
130static void fwohci_txd __P((struct fwohci_softc *, struct fwohci_dbch *));
131static void fwohci_start_atq __P((struct firewire_comm *));
132static void fwohci_start_ats __P((struct firewire_comm *));
133static void fwohci_start __P((struct fwohci_softc *, struct fwohci_dbch *));
134static void fwohci_drain_atq __P((struct firewire_comm *, struct fw_xfer *));
135static void fwohci_drain_ats __P((struct firewire_comm *, struct fw_xfer *));
136static void fwohci_drain __P((struct firewire_comm *, struct fw_xfer *, struct fwohci_dbch *));
137static u_int32_t fwphy_wrdata __P(( struct fwohci_softc *, u_int32_t, u_int32_t));
138static u_int32_t fwphy_rddata __P(( struct fwohci_softc *, u_int32_t));
139static int fwohci_rx_enable __P((struct fwohci_softc *, struct fwohci_dbch *));
140static int fwohci_tx_enable __P((struct fwohci_softc *, struct fwohci_dbch *));
141static int fwohci_irx_enable __P((struct firewire_comm *, int));
142static int fwohci_irxpp_enable __P((struct firewire_comm *, int));
143static int fwohci_irxbuf_enable __P((struct firewire_comm *, int));
144static int fwohci_irx_disable __P((struct firewire_comm *, int));
145static void fwohci_irx_post __P((struct firewire_comm *, u_int32_t *));
146static int fwohci_itxbuf_enable __P((struct firewire_comm *, int));
147static int fwohci_itx_disable __P((struct firewire_comm *, int));
148static void fwohci_timeout __P((void *));
149static void fwohci_poll __P((struct firewire_comm *, int, int));
150static void fwohci_set_intr __P((struct firewire_comm *, int));
151static int fwohci_add_rx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *, void *));
152static int fwohci_add_tx_buf __P((struct fwohcidb_tr *, unsigned short, int, void *));
153static void dump_db __P((struct fwohci_softc *, u_int32_t));
154static void print_db __P((volatile struct fwohcidb *, u_int32_t , u_int32_t));
155static void dump_dma __P((struct fwohci_softc *, u_int32_t));
156static u_int32_t fwohci_cyctimer __P((struct firewire_comm *));
157static void fwohci_rbuf_update __P((struct fwohci_softc *, int));
158static void fwohci_tbuf_update __P((struct fwohci_softc *, int));
159void fwohci_txbufdb __P((struct fwohci_softc *, int , struct fw_bulkxfer *));
160
161/*
162 * memory allocated for DMA programs
163 */
164#define DMA_PROG_ALLOC (8 * PAGE_SIZE)
165
166/* #define NDB 1024 */
167#define NDB FWMAXQUEUE
168#define NDVDB (DVBUF * NDB)
169
170#define OHCI_VERSION 0x00
171#define OHCI_CROMHDR 0x18
172#define OHCI_BUS_OPT 0x20
173#define OHCI_BUSIRMC (1 << 31)
174#define OHCI_BUSCMC (1 << 30)
175#define OHCI_BUSISC (1 << 29)
176#define OHCI_BUSBMC (1 << 28)
177#define OHCI_BUSPMC (1 << 27)
178#define OHCI_BUSFNC OHCI_BUSIRMC | OHCI_BUSCMC | OHCI_BUSISC |\
179 OHCI_BUSBMC | OHCI_BUSPMC
180
181#define OHCI_EUID_HI 0x24
182#define OHCI_EUID_LO 0x28
183
184#define OHCI_CROMPTR 0x34
185#define OHCI_HCCCTL 0x50
186#define OHCI_HCCCTLCLR 0x54
187#define OHCI_AREQHI 0x100
188#define OHCI_AREQHICLR 0x104
189#define OHCI_AREQLO 0x108
190#define OHCI_AREQLOCLR 0x10c
191#define OHCI_PREQHI 0x110
192#define OHCI_PREQHICLR 0x114
193#define OHCI_PREQLO 0x118
194#define OHCI_PREQLOCLR 0x11c
195#define OHCI_PREQUPPER 0x120
196
197#define OHCI_SID_BUF 0x64
198#define OHCI_SID_CNT 0x68
199#define OHCI_SID_CNT_MASK 0xffc
200
201#define OHCI_IT_STAT 0x90
202#define OHCI_IT_STATCLR 0x94
203#define OHCI_IT_MASK 0x98
204#define OHCI_IT_MASKCLR 0x9c
205
206#define OHCI_IR_STAT 0xa0
207#define OHCI_IR_STATCLR 0xa4
208#define OHCI_IR_MASK 0xa8
209#define OHCI_IR_MASKCLR 0xac
210
211#define OHCI_LNKCTL 0xe0
212#define OHCI_LNKCTLCLR 0xe4
213
214#define OHCI_PHYACCESS 0xec
215#define OHCI_CYCLETIMER 0xf0
216
217#define OHCI_DMACTL(off) (off)
218#define OHCI_DMACTLCLR(off) (off + 4)
219#define OHCI_DMACMD(off) (off + 0xc)
220#define OHCI_DMAMATCH(off) (off + 0x10)
221
222#define OHCI_ATQOFF 0x180
223#define OHCI_ATQCTL OHCI_ATQOFF
224#define OHCI_ATQCTLCLR (OHCI_ATQOFF + 4)
225#define OHCI_ATQCMD (OHCI_ATQOFF + 0xc)
226#define OHCI_ATQMATCH (OHCI_ATQOFF + 0x10)
227
228#define OHCI_ATSOFF 0x1a0
229#define OHCI_ATSCTL OHCI_ATSOFF
230#define OHCI_ATSCTLCLR (OHCI_ATSOFF + 4)
231#define OHCI_ATSCMD (OHCI_ATSOFF + 0xc)
232#define OHCI_ATSMATCH (OHCI_ATSOFF + 0x10)
233
234#define OHCI_ARQOFF 0x1c0
235#define OHCI_ARQCTL OHCI_ARQOFF
236#define OHCI_ARQCTLCLR (OHCI_ARQOFF + 4)
237#define OHCI_ARQCMD (OHCI_ARQOFF + 0xc)
238#define OHCI_ARQMATCH (OHCI_ARQOFF + 0x10)
239
240#define OHCI_ARSOFF 0x1e0
241#define OHCI_ARSCTL OHCI_ARSOFF
242#define OHCI_ARSCTLCLR (OHCI_ARSOFF + 4)
243#define OHCI_ARSCMD (OHCI_ARSOFF + 0xc)
244#define OHCI_ARSMATCH (OHCI_ARSOFF + 0x10)
245
246#define OHCI_ITOFF(CH) (0x200 + 0x10 * (CH))
247#define OHCI_ITCTL(CH) (OHCI_ITOFF(CH))
248#define OHCI_ITCTLCLR(CH) (OHCI_ITOFF(CH) + 4)
249#define OHCI_ITCMD(CH) (OHCI_ITOFF(CH) + 0xc)
250
251#define OHCI_IROFF(CH) (0x400 + 0x20 * (CH))
252#define OHCI_IRCTL(CH) (OHCI_IROFF(CH))
253#define OHCI_IRCTLCLR(CH) (OHCI_IROFF(CH) + 4)
254#define OHCI_IRCMD(CH) (OHCI_IROFF(CH) + 0xc)
255#define OHCI_IRMATCH(CH) (OHCI_IROFF(CH) + 0x10)
256
257d_ioctl_t fwohci_ioctl;
258
259/*
260 * Communication with PHY device
261 */
262static u_int32_t
263fwphy_wrdata( struct fwohci_softc *sc, u_int32_t addr, u_int32_t data)
264{
265 u_int32_t fun;
266
267 addr &= 0xf;
268 data &= 0xff;
269
270 fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA));
271 OWRITE(sc, OHCI_PHYACCESS, fun);
272 DELAY(100);
273
274 return(fwphy_rddata( sc, addr));
275}
276
277static u_int32_t
278fwohci_set_bus_manager(struct firewire_comm *fc, u_int node)
279{
280 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
281 int i;
282 u_int32_t bm;
283
284#define OHCI_CSR_DATA 0x0c
285#define OHCI_CSR_COMP 0x10
286#define OHCI_CSR_CONT 0x14
287#define OHCI_BUS_MANAGER_ID 0
288
289 OWRITE(sc, OHCI_CSR_DATA, node);
290 OWRITE(sc, OHCI_CSR_COMP, 0x3f);
291 OWRITE(sc, OHCI_CSR_CONT, OHCI_BUS_MANAGER_ID);
292 for (i = 0; !(OREAD(sc, OHCI_CSR_CONT) & (1<<31)) && (i < 1000); i++)
293 DELAY(100);
294 bm = OREAD(sc, OHCI_CSR_DATA);
295 if((bm & 0x3f) == 0x3f){
296 printf("fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i);
295 if((bm & 0x3f) == 0x3f)
297 bm = node;
296 bm = node;
298 }else{
299 printf("fw_set_bus_manager: %d-X%d (loop=%d)\n", bm, node, i);
300 }
297 if (bootverbose)
298 device_printf(sc->fc.dev,
299 "fw_set_bus_manager: %d->%d (loop=%d)\n", bm, node, i);
301
302 return(bm);
303}
304
305static u_int32_t
306fwphy_rddata(struct fwohci_softc *sc, u_int addr)
307{
308 u_int32_t fun;
309 u_int i;
310
311 addr &= 0xf;
312 fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
313 OWRITE(sc, OHCI_PHYACCESS, fun);
314 for ( i = 0 ; i < 1000 ; i ++ ){
315 fun = OREAD(sc, OHCI_PHYACCESS);
316 if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
317 break;
318 DELAY(1000);
319 }
320 if( i >= 1000)
321 device_printf(sc->fc.dev, "cannot read phy\n");
322 return((fun >> PHYDEV_RDDATA )& 0xff);
323}
324/* Device specific ioctl. */
325int
326fwohci_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
327{
328 struct firewire_softc *sc;
329 struct fwohci_softc *fc;
330 int unit = DEV2UNIT(dev);
331 int err = 0;
332 struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data;
333 u_int32_t *dmach = (u_int32_t *) data;
334
335 sc = devclass_get_softc(firewire_devclass, unit);
336 if(sc == NULL){
337 return(EINVAL);
338 }
339 fc = (struct fwohci_softc *)sc->fc;
340
341 if (!data)
342 return(EINVAL);
343
344 switch (cmd) {
345 case FWOHCI_WRREG:
346#define OHCI_MAX_REG 0x800
347 if(reg->addr <= OHCI_MAX_REG){
348 OWRITE(fc, reg->addr, reg->data);
349 reg->data = OREAD(fc, reg->addr);
350 }else{
351 err = EINVAL;
352 }
353 break;
354 case FWOHCI_RDREG:
355 if(reg->addr <= OHCI_MAX_REG){
356 reg->data = OREAD(fc, reg->addr);
357 }else{
358 err = EINVAL;
359 }
360 break;
361/* Read DMA descriptors for debug */
362 case DUMPDMA:
363 if(*dmach <= OHCI_MAX_DMA_CH ){
364 dump_dma(fc, *dmach);
365 dump_db(fc, *dmach);
366 }else{
367 err = EINVAL;
368 }
369 break;
370 default:
371 break;
372 }
373 return err;
374}
375
376int
377fwohci_init(struct fwohci_softc *sc, device_t dev)
378{
379 int err = 0;
380 int i;
381 u_int32_t reg, reg2;
382 struct fwohcidb_tr *db_tr;
383 int e1394a = 1;
384
385 reg = OREAD(sc, OHCI_VERSION);
386 device_printf(dev, "OHCI version %x.%x (ROM=%d)\n",
387 (reg>>16) & 0xff, reg & 0xff, (reg>>24) & 1);
388
389/* XXX: Available Isochrounous DMA channel probe */
390 for( i = 0 ; i < 0x20 ; i ++ ){
391 OWRITE(sc, OHCI_IRCTL(i), OHCI_CNTL_DMA_RUN);
392 reg = OREAD(sc, OHCI_IRCTL(i));
393 if(!(reg & OHCI_CNTL_DMA_RUN)) break;
394 OWRITE(sc, OHCI_ITCTL(i), OHCI_CNTL_DMA_RUN);
395 reg = OREAD(sc, OHCI_ITCTL(i));
396 if(!(reg & OHCI_CNTL_DMA_RUN)) break;
397 }
398 sc->fc.nisodma = i;
399 device_printf(dev, "No. of Isochronous channel is %d.\n", i);
400
401 sc->fc.arq = &sc->arrq.xferq;
402 sc->fc.ars = &sc->arrs.xferq;
403 sc->fc.atq = &sc->atrq.xferq;
404 sc->fc.ats = &sc->atrs.xferq;
405
406 sc->arrq.xferq.start = NULL;
407 sc->arrs.xferq.start = NULL;
408 sc->atrq.xferq.start = fwohci_start_atq;
409 sc->atrs.xferq.start = fwohci_start_ats;
410
411 sc->arrq.xferq.drain = NULL;
412 sc->arrs.xferq.drain = NULL;
413 sc->atrq.xferq.drain = fwohci_drain_atq;
414 sc->atrs.xferq.drain = fwohci_drain_ats;
415
416 sc->arrq.ndesc = 1;
417 sc->arrs.ndesc = 1;
418 sc->atrq.ndesc = 10;
419 sc->atrs.ndesc = 10 / 2;
420
421 sc->arrq.ndb = NDB;
422 sc->arrs.ndb = NDB / 2;
423 sc->atrq.ndb = NDB;
424 sc->atrs.ndb = NDB / 2;
425
426 sc->arrq.dummy = NULL;
427 sc->arrs.dummy = NULL;
428 sc->atrq.dummy = NULL;
429 sc->atrs.dummy = NULL;
430 for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
431 sc->fc.it[i] = &sc->it[i].xferq;
432 sc->fc.ir[i] = &sc->ir[i].xferq;
433 sc->it[i].ndb = 0;
434 sc->ir[i].ndb = 0;
435 }
436
437 sc->fc.tcode = tinfo;
438
439 sc->cromptr = (u_int32_t *)
440 contigmalloc(CROMSIZE * 2, M_DEVBUF, M_NOWAIT, 0, ~0, 1<<10, 0);
441
442 if(sc->cromptr == NULL){
443 return ENOMEM;
444 }
445 sc->fc.dev = dev;
446 sc->fc.config_rom = &(sc->cromptr[CROMSIZE/4]);
447
448 sc->fc.config_rom[1] = 0x31333934;
449 sc->fc.config_rom[2] = 0xf000a002;
450 sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI);
451 sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO);
452 sc->fc.config_rom[5] = 0;
453 sc->fc.config_rom[0] = (4 << 24) | (5 << 16);
454
455 sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4);
456
457
458 fw_init(&sc->fc);
459
460/* Now stopping all DMA channel */
461 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
462 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
463 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
464 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
465
466 OWRITE(sc, OHCI_IR_MASKCLR, ~0);
467 for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
468 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
469 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
470 }
471
472/* FLUSH FIFO and reset Transmitter/Reciever */
473 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
300
301 return(bm);
302}
303
304static u_int32_t
305fwphy_rddata(struct fwohci_softc *sc, u_int addr)
306{
307 u_int32_t fun;
308 u_int i;
309
310 addr &= 0xf;
311 fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
312 OWRITE(sc, OHCI_PHYACCESS, fun);
313 for ( i = 0 ; i < 1000 ; i ++ ){
314 fun = OREAD(sc, OHCI_PHYACCESS);
315 if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
316 break;
317 DELAY(1000);
318 }
319 if( i >= 1000)
320 device_printf(sc->fc.dev, "cannot read phy\n");
321 return((fun >> PHYDEV_RDDATA )& 0xff);
322}
323/* Device specific ioctl. */
324int
325fwohci_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
326{
327 struct firewire_softc *sc;
328 struct fwohci_softc *fc;
329 int unit = DEV2UNIT(dev);
330 int err = 0;
331 struct fw_reg_req_t *reg = (struct fw_reg_req_t *) data;
332 u_int32_t *dmach = (u_int32_t *) data;
333
334 sc = devclass_get_softc(firewire_devclass, unit);
335 if(sc == NULL){
336 return(EINVAL);
337 }
338 fc = (struct fwohci_softc *)sc->fc;
339
340 if (!data)
341 return(EINVAL);
342
343 switch (cmd) {
344 case FWOHCI_WRREG:
345#define OHCI_MAX_REG 0x800
346 if(reg->addr <= OHCI_MAX_REG){
347 OWRITE(fc, reg->addr, reg->data);
348 reg->data = OREAD(fc, reg->addr);
349 }else{
350 err = EINVAL;
351 }
352 break;
353 case FWOHCI_RDREG:
354 if(reg->addr <= OHCI_MAX_REG){
355 reg->data = OREAD(fc, reg->addr);
356 }else{
357 err = EINVAL;
358 }
359 break;
360/* Read DMA descriptors for debug */
361 case DUMPDMA:
362 if(*dmach <= OHCI_MAX_DMA_CH ){
363 dump_dma(fc, *dmach);
364 dump_db(fc, *dmach);
365 }else{
366 err = EINVAL;
367 }
368 break;
369 default:
370 break;
371 }
372 return err;
373}
374
375int
376fwohci_init(struct fwohci_softc *sc, device_t dev)
377{
378 int err = 0;
379 int i;
380 u_int32_t reg, reg2;
381 struct fwohcidb_tr *db_tr;
382 int e1394a = 1;
383
384 reg = OREAD(sc, OHCI_VERSION);
385 device_printf(dev, "OHCI version %x.%x (ROM=%d)\n",
386 (reg>>16) & 0xff, reg & 0xff, (reg>>24) & 1);
387
388/* XXX: Available Isochrounous DMA channel probe */
389 for( i = 0 ; i < 0x20 ; i ++ ){
390 OWRITE(sc, OHCI_IRCTL(i), OHCI_CNTL_DMA_RUN);
391 reg = OREAD(sc, OHCI_IRCTL(i));
392 if(!(reg & OHCI_CNTL_DMA_RUN)) break;
393 OWRITE(sc, OHCI_ITCTL(i), OHCI_CNTL_DMA_RUN);
394 reg = OREAD(sc, OHCI_ITCTL(i));
395 if(!(reg & OHCI_CNTL_DMA_RUN)) break;
396 }
397 sc->fc.nisodma = i;
398 device_printf(dev, "No. of Isochronous channel is %d.\n", i);
399
400 sc->fc.arq = &sc->arrq.xferq;
401 sc->fc.ars = &sc->arrs.xferq;
402 sc->fc.atq = &sc->atrq.xferq;
403 sc->fc.ats = &sc->atrs.xferq;
404
405 sc->arrq.xferq.start = NULL;
406 sc->arrs.xferq.start = NULL;
407 sc->atrq.xferq.start = fwohci_start_atq;
408 sc->atrs.xferq.start = fwohci_start_ats;
409
410 sc->arrq.xferq.drain = NULL;
411 sc->arrs.xferq.drain = NULL;
412 sc->atrq.xferq.drain = fwohci_drain_atq;
413 sc->atrs.xferq.drain = fwohci_drain_ats;
414
415 sc->arrq.ndesc = 1;
416 sc->arrs.ndesc = 1;
417 sc->atrq.ndesc = 10;
418 sc->atrs.ndesc = 10 / 2;
419
420 sc->arrq.ndb = NDB;
421 sc->arrs.ndb = NDB / 2;
422 sc->atrq.ndb = NDB;
423 sc->atrs.ndb = NDB / 2;
424
425 sc->arrq.dummy = NULL;
426 sc->arrs.dummy = NULL;
427 sc->atrq.dummy = NULL;
428 sc->atrs.dummy = NULL;
429 for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
430 sc->fc.it[i] = &sc->it[i].xferq;
431 sc->fc.ir[i] = &sc->ir[i].xferq;
432 sc->it[i].ndb = 0;
433 sc->ir[i].ndb = 0;
434 }
435
436 sc->fc.tcode = tinfo;
437
438 sc->cromptr = (u_int32_t *)
439 contigmalloc(CROMSIZE * 2, M_DEVBUF, M_NOWAIT, 0, ~0, 1<<10, 0);
440
441 if(sc->cromptr == NULL){
442 return ENOMEM;
443 }
444 sc->fc.dev = dev;
445 sc->fc.config_rom = &(sc->cromptr[CROMSIZE/4]);
446
447 sc->fc.config_rom[1] = 0x31333934;
448 sc->fc.config_rom[2] = 0xf000a002;
449 sc->fc.config_rom[3] = OREAD(sc, OHCI_EUID_HI);
450 sc->fc.config_rom[4] = OREAD(sc, OHCI_EUID_LO);
451 sc->fc.config_rom[5] = 0;
452 sc->fc.config_rom[0] = (4 << 24) | (5 << 16);
453
454 sc->fc.config_rom[0] |= fw_crc16(&sc->fc.config_rom[1], 5*4);
455
456
457 fw_init(&sc->fc);
458
459/* Now stopping all DMA channel */
460 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
461 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
462 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
463 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
464
465 OWRITE(sc, OHCI_IR_MASKCLR, ~0);
466 for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
467 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
468 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
469 }
470
471/* FLUSH FIFO and reset Transmitter/Reciever */
472 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
474 device_printf(dev, "resetting OHCI...");
473 if (bootverbose)
474 device_printf(dev, "resetting OHCI...");
475 i = 0;
476 while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
477 if (i++ > 100) break;
478 DELAY(1000);
479 }
475 i = 0;
476 while(OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_RESET) {
477 if (i++ > 100) break;
478 DELAY(1000);
479 }
480 printf("done (%d)\n", i);
480 if (bootverbose)
481 printf("done (%d)\n", i);
481 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
482 /* XXX wait for SCLK. */
483 DELAY(100000);
484
485 reg = OREAD(sc, OHCI_BUS_OPT);
486 reg2 = reg | OHCI_BUSFNC;
487 /* XXX */
488 if (((reg & 0x0000f000) >> 12) < 10)
489 reg2 = (reg2 & 0xffff0fff) | (10 << 12);
482 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
483 /* XXX wait for SCLK. */
484 DELAY(100000);
485
486 reg = OREAD(sc, OHCI_BUS_OPT);
487 reg2 = reg | OHCI_BUSFNC;
488 /* XXX */
489 if (((reg & 0x0000f000) >> 12) < 10)
490 reg2 = (reg2 & 0xffff0fff) | (10 << 12);
490 device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
491 if (bootverbose)
492 device_printf(dev, "BUS_OPT 0x%x -> 0x%x\n", reg, reg2);
491 OWRITE(sc, OHCI_BUS_OPT, reg2);
492
493 OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
494 OWRITE(sc, OHCI_CROMPTR, vtophys(&sc->fc.config_rom[0]));
495 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
496 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
497
498/*
499 * probe PHY parameters
500 * 0. to prove PHY version, whether compliance of 1394a.
501 * 1. to probe maximum speed supported by the PHY and
502 * number of port supported by core-logic.
503 * It is not actually available port on your PC .
504 */
505 /* Wait a while */
506 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
507#if 0
508 /* try again */
509 DELAY(1000);
510 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
511#endif
512 if((reg >> 5) != 7 ){
513 sc->fc.mode &= ~FWPHYASYST;
514 sc->fc.nport = reg & FW_PHY_NP;
515 sc->fc.speed = reg & FW_PHY_SPD >> 6;
516 if (sc->fc.speed > MAX_SPEED) {
517 device_printf(dev, "invalid speed %d (fixed to %d).\n",
518 sc->fc.speed, MAX_SPEED);
519 sc->fc.speed = MAX_SPEED;
520 }
521 sc->fc.maxrec = maxrec[sc->fc.speed];
522 device_printf(dev,
523 "Link 1394 only %s, %d ports, maxrec %d bytes.\n",
524 linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec);
525 }else{
526 reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
527 sc->fc.mode |= FWPHYASYST;
528 sc->fc.nport = reg & FW_PHY_NP;
529 sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
530 if (sc->fc.speed > MAX_SPEED) {
531 device_printf(dev, "invalid speed %d (fixed to %d).\n",
532 sc->fc.speed, MAX_SPEED);
533 sc->fc.speed = MAX_SPEED;
534 }
535 sc->fc.maxrec = maxrec[sc->fc.speed];
536 device_printf(dev,
537 "Link 1394a available %s, %d ports, maxrec %d bytes.\n",
538 linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec);
539
540 /* check programPhyEnable */
541 reg2 = fwphy_rddata(sc, 5);
542#if 0
543 if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
544#else /* XXX force to enable 1394a */
545 if (e1394a) {
546#endif
493 OWRITE(sc, OHCI_BUS_OPT, reg2);
494
495 OWRITE(sc, OHCI_CROMHDR, sc->fc.config_rom[0]);
496 OWRITE(sc, OHCI_CROMPTR, vtophys(&sc->fc.config_rom[0]));
497 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_BIGEND);
498 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_POSTWR);
499
500/*
501 * probe PHY parameters
502 * 0. to prove PHY version, whether compliance of 1394a.
503 * 1. to probe maximum speed supported by the PHY and
504 * number of port supported by core-logic.
505 * It is not actually available port on your PC .
506 */
507 /* Wait a while */
508 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
509#if 0
510 /* try again */
511 DELAY(1000);
512 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
513#endif
514 if((reg >> 5) != 7 ){
515 sc->fc.mode &= ~FWPHYASYST;
516 sc->fc.nport = reg & FW_PHY_NP;
517 sc->fc.speed = reg & FW_PHY_SPD >> 6;
518 if (sc->fc.speed > MAX_SPEED) {
519 device_printf(dev, "invalid speed %d (fixed to %d).\n",
520 sc->fc.speed, MAX_SPEED);
521 sc->fc.speed = MAX_SPEED;
522 }
523 sc->fc.maxrec = maxrec[sc->fc.speed];
524 device_printf(dev,
525 "Link 1394 only %s, %d ports, maxrec %d bytes.\n",
526 linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec);
527 }else{
528 reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
529 sc->fc.mode |= FWPHYASYST;
530 sc->fc.nport = reg & FW_PHY_NP;
531 sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
532 if (sc->fc.speed > MAX_SPEED) {
533 device_printf(dev, "invalid speed %d (fixed to %d).\n",
534 sc->fc.speed, MAX_SPEED);
535 sc->fc.speed = MAX_SPEED;
536 }
537 sc->fc.maxrec = maxrec[sc->fc.speed];
538 device_printf(dev,
539 "Link 1394a available %s, %d ports, maxrec %d bytes.\n",
540 linkspeed[sc->fc.speed], sc->fc.nport, sc->fc.maxrec);
541
542 /* check programPhyEnable */
543 reg2 = fwphy_rddata(sc, 5);
544#if 0
545 if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
546#else /* XXX force to enable 1394a */
547 if (e1394a) {
548#endif
547 device_printf(dev, "Enable 1394a Enhancements\n");
549 if (bootverbose)
550 device_printf(dev,
551 "Enable 1394a Enhancements\n");
548 /* enable EAA EMC */
549 reg2 |= 0x03;
550 /* set aPhyEnhanceEnable */
551 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
552 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
553 } else {
554 /* for safe */
555 reg2 &= ~0x83;
556 }
557 reg2 = fwphy_wrdata(sc, 5, reg2);
558 }
559
560 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
561 if((reg >> 5) == 7 ){
562 reg = fwphy_rddata(sc, 4);
563 reg |= 1 << 6;
564 fwphy_wrdata(sc, 4, reg);
565 reg = fwphy_rddata(sc, 4);
566 }
567
568/* SID recieve buffer must allign 2^11 */
569#define OHCI_SIDSIZE (1 << 11)
570 sc->fc.sid_buf = (u_int32_t *) vm_page_alloc_contig( OHCI_SIDSIZE,
571 0x10000, 0xffffffff, OHCI_SIDSIZE);
572 OWRITE(sc, OHCI_SID_BUF, vtophys(sc->fc.sid_buf));
573 sc->fc.sid_buf++;
574 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
575
576 fwohci_db_init(&sc->arrq);
577 fwohci_db_init(&sc->arrs);
578
579 fwohci_db_init(&sc->atrq);
580 fwohci_db_init(&sc->atrs);
581
582 reg = OREAD(sc, FWOHCIGUID_H);
583 for( i = 0 ; i < 4 ; i ++){
584 sc->fc.eui[3 - i] = reg & 0xff;
585 reg = reg >> 8;
586 }
587 reg = OREAD(sc, FWOHCIGUID_L);
588 for( i = 0 ; i < 4 ; i ++){
589 sc->fc.eui[7 - i] = reg & 0xff;
590 reg = reg >> 8;
591 }
592 device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
593 sc->fc.eui[0], sc->fc.eui[1], sc->fc.eui[2], sc->fc.eui[3],
594 sc->fc.eui[4], sc->fc.eui[5], sc->fc.eui[6], sc->fc.eui[7]);
595 sc->fc.ioctl = fwohci_ioctl;
596 sc->fc.cyctimer = fwohci_cyctimer;
597 sc->fc.set_bmr = fwohci_set_bus_manager;
598 sc->fc.ibr = fwohci_ibr;
599 sc->fc.irx_enable = fwohci_irx_enable;
600 sc->fc.irx_disable = fwohci_irx_disable;
601
602 sc->fc.itx_enable = fwohci_itxbuf_enable;
603 sc->fc.itx_disable = fwohci_itx_disable;
604 sc->fc.irx_post = fwohci_irx_post;
605 sc->fc.itx_post = NULL;
606 sc->fc.timeout = fwohci_timeout;
607 sc->fc.poll = fwohci_poll;
608 sc->fc.set_intr = fwohci_set_intr;
609
610 /* enable link */
611 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
612 fw_busreset(&sc->fc);
613 fwohci_rx_enable(sc, &sc->arrq);
614 fwohci_rx_enable(sc, &sc->arrs);
615
616 for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ;
617 i ++, db_tr = STAILQ_NEXT(db_tr, link)){
618 db_tr->xfer = NULL;
619 }
620 for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ;
621 i ++, db_tr = STAILQ_NEXT(db_tr, link)){
622 db_tr->xfer = NULL;
623 }
624 sc->atrq.flags = sc->atrs.flags = 0;
625
626 OWRITE(sc, FWOHCI_RETRY,
627 (0xffff << 16 )| (0x0f << 8) | (0x0f << 4) | 0x0f) ;
628 OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
629 OWRITE(sc, FWOHCI_INTMASK,
630 OHCI_INT_ERR | OHCI_INT_PHY_SID
631 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
632 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
633 | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
634 fwohci_set_intr(&sc->fc, 1);
635
636 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
637 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
638
639 return err;
640}
641
642void
643fwohci_timeout(void *arg)
644{
645 struct fwohci_softc *sc;
646
647 sc = (struct fwohci_softc *)arg;
648 sc->fc.timeouthandle = timeout(fwohci_timeout,
649 (void *)sc, FW_XFERTIMEOUT * hz * 10);
650}
651
652u_int32_t
653fwohci_cyctimer(struct firewire_comm *fc)
654{
655 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
656 return(OREAD(sc, OHCI_CYCLETIMER));
657}
658
659#define LAST_DB(dbtr, db) do { \
660 struct fwohcidb_tr *_dbtr = (dbtr); \
661 int _cnt = _dbtr->dbcnt; \
662 db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \
663} while (0)
664
665static void
666fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
667{
668 int i, s;
669 int tcode, hdr_len, hdr_off, len;
670 int fsegment = -1;
671 u_int32_t off;
672 struct fw_xfer *xfer;
673 struct fw_pkt *fp;
674 volatile struct fwohci_txpkthdr *ohcifp;
675 struct fwohcidb_tr *db_tr;
676 volatile struct fwohcidb *db;
677 struct mbuf *m;
678 struct tcode_info *info;
679
680 if(&sc->atrq == dbch){
681 off = OHCI_ATQOFF;
682 }else if(&sc->atrs == dbch){
683 off = OHCI_ATSOFF;
684 }else{
685 return;
686 }
687
688 if (dbch->flags & FWOHCI_DBCH_FULL)
689 return;
690
691 s = splfw();
692 db_tr = dbch->top;
693txloop:
694 xfer = STAILQ_FIRST(&dbch->xferq.q);
695 if(xfer == NULL){
696 goto kick;
697 }
698 if(dbch->xferq.queued == 0 ){
699 device_printf(sc->fc.dev, "TX queue empty\n");
700 }
701 STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
702 db_tr->xfer = xfer;
703 xfer->state = FWXF_START;
704 dbch->xferq.packets++;
705
706 fp = (struct fw_pkt *)(xfer->send.buf + xfer->send.off);
707 tcode = fp->mode.common.tcode;
708
709 ohcifp = (volatile struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
710 info = &tinfo[tcode];
711 hdr_len = hdr_off = info->hdr_len;
712 /* fw_asyreq must pass valid send.len */
713 len = xfer->send.len;
714 for( i = 0 ; i < hdr_off ; i+= 4){
715 ohcifp->mode.ld[i/4] = ntohl(fp->mode.ld[i/4]);
716 }
717 ohcifp->mode.common.spd = xfer->spd;
718 if (tcode == FWTCODE_STREAM ){
719 hdr_len = 8;
720 ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
721 } else if (tcode == FWTCODE_PHY) {
722 hdr_len = 12;
723 ohcifp->mode.ld[1] = ntohl(fp->mode.ld[1]);
724 ohcifp->mode.ld[2] = ntohl(fp->mode.ld[2]);
725 ohcifp->mode.common.spd = 0;
726 ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
727 } else {
728 ohcifp->mode.asycomm.dst = ntohs(fp->mode.hdr.dst);
729 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
730 ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
731 }
732 db = &db_tr->db[0];
733 db->db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len;
734 db->db.desc.status = 0;
735/* Specify bound timer of asy. responce */
736 if(&sc->atrs == dbch){
737 db->db.desc.count
738 = (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13);
739 }
740
741 db_tr->dbcnt = 2;
742 db = &db_tr->db[db_tr->dbcnt];
743 if(len > hdr_off){
744 if (xfer->mbuf == NULL) {
745 db->db.desc.addr
746 = vtophys(xfer->send.buf + xfer->send.off) + hdr_off;
747 db->db.desc.cmd
748 = OHCI_OUTPUT_MORE | ((len - hdr_off) & 0xffff);
749 db->db.desc.status = 0;
750
751 db_tr->dbcnt++;
752 } else {
753 /* XXX we assume mbuf chain is shorter than ndesc */
754 m = xfer->mbuf;
755 do {
756 db->db.desc.addr
757 = vtophys(mtod(m, caddr_t));
758 db->db.desc.cmd = OHCI_OUTPUT_MORE | m->m_len;
759 db->db.desc.status = 0;
760 db++;
761 db_tr->dbcnt++;
762 m = m->m_next;
763 } while (m != NULL);
764 }
765 }
766 /* last db */
767 LAST_DB(db_tr, db);
768 db->db.desc.cmd |= OHCI_OUTPUT_LAST
769 | OHCI_INTERRUPT_ALWAYS
770 | OHCI_BRANCH_ALWAYS;
771 db->db.desc.depend = vtophys(STAILQ_NEXT(db_tr, link)->db);
772
773 if(fsegment == -1 )
774 fsegment = db_tr->dbcnt;
775 if (dbch->pdb_tr != NULL) {
776 LAST_DB(dbch->pdb_tr, db);
777 db->db.desc.depend |= db_tr->dbcnt;
778 }
779 dbch->pdb_tr = db_tr;
780 db_tr = STAILQ_NEXT(db_tr, link);
781 if(db_tr != dbch->bottom){
782 goto txloop;
783 } else {
552 /* enable EAA EMC */
553 reg2 |= 0x03;
554 /* set aPhyEnhanceEnable */
555 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_PHYEN);
556 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_PRPHY);
557 } else {
558 /* for safe */
559 reg2 &= ~0x83;
560 }
561 reg2 = fwphy_wrdata(sc, 5, reg2);
562 }
563
564 reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
565 if((reg >> 5) == 7 ){
566 reg = fwphy_rddata(sc, 4);
567 reg |= 1 << 6;
568 fwphy_wrdata(sc, 4, reg);
569 reg = fwphy_rddata(sc, 4);
570 }
571
572/* SID recieve buffer must allign 2^11 */
573#define OHCI_SIDSIZE (1 << 11)
574 sc->fc.sid_buf = (u_int32_t *) vm_page_alloc_contig( OHCI_SIDSIZE,
575 0x10000, 0xffffffff, OHCI_SIDSIZE);
576 OWRITE(sc, OHCI_SID_BUF, vtophys(sc->fc.sid_buf));
577 sc->fc.sid_buf++;
578 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_SID);
579
580 fwohci_db_init(&sc->arrq);
581 fwohci_db_init(&sc->arrs);
582
583 fwohci_db_init(&sc->atrq);
584 fwohci_db_init(&sc->atrs);
585
586 reg = OREAD(sc, FWOHCIGUID_H);
587 for( i = 0 ; i < 4 ; i ++){
588 sc->fc.eui[3 - i] = reg & 0xff;
589 reg = reg >> 8;
590 }
591 reg = OREAD(sc, FWOHCIGUID_L);
592 for( i = 0 ; i < 4 ; i ++){
593 sc->fc.eui[7 - i] = reg & 0xff;
594 reg = reg >> 8;
595 }
596 device_printf(dev, "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
597 sc->fc.eui[0], sc->fc.eui[1], sc->fc.eui[2], sc->fc.eui[3],
598 sc->fc.eui[4], sc->fc.eui[5], sc->fc.eui[6], sc->fc.eui[7]);
599 sc->fc.ioctl = fwohci_ioctl;
600 sc->fc.cyctimer = fwohci_cyctimer;
601 sc->fc.set_bmr = fwohci_set_bus_manager;
602 sc->fc.ibr = fwohci_ibr;
603 sc->fc.irx_enable = fwohci_irx_enable;
604 sc->fc.irx_disable = fwohci_irx_disable;
605
606 sc->fc.itx_enable = fwohci_itxbuf_enable;
607 sc->fc.itx_disable = fwohci_itx_disable;
608 sc->fc.irx_post = fwohci_irx_post;
609 sc->fc.itx_post = NULL;
610 sc->fc.timeout = fwohci_timeout;
611 sc->fc.poll = fwohci_poll;
612 sc->fc.set_intr = fwohci_set_intr;
613
614 /* enable link */
615 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LINKEN);
616 fw_busreset(&sc->fc);
617 fwohci_rx_enable(sc, &sc->arrq);
618 fwohci_rx_enable(sc, &sc->arrs);
619
620 for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ;
621 i ++, db_tr = STAILQ_NEXT(db_tr, link)){
622 db_tr->xfer = NULL;
623 }
624 for( i = 0, db_tr = sc->atrs.top; i < sc->atrs.ndb ;
625 i ++, db_tr = STAILQ_NEXT(db_tr, link)){
626 db_tr->xfer = NULL;
627 }
628 sc->atrq.flags = sc->atrs.flags = 0;
629
630 OWRITE(sc, FWOHCI_RETRY,
631 (0xffff << 16 )| (0x0f << 8) | (0x0f << 4) | 0x0f) ;
632 OWRITE(sc, FWOHCI_INTMASKCLR, ~0);
633 OWRITE(sc, FWOHCI_INTMASK,
634 OHCI_INT_ERR | OHCI_INT_PHY_SID
635 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
636 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
637 | OHCI_INT_PHY_BUS_R | OHCI_INT_PW_ERR);
638 fwohci_set_intr(&sc->fc, 1);
639
640 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
641 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
642
643 return err;
644}
645
646void
647fwohci_timeout(void *arg)
648{
649 struct fwohci_softc *sc;
650
651 sc = (struct fwohci_softc *)arg;
652 sc->fc.timeouthandle = timeout(fwohci_timeout,
653 (void *)sc, FW_XFERTIMEOUT * hz * 10);
654}
655
656u_int32_t
657fwohci_cyctimer(struct firewire_comm *fc)
658{
659 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
660 return(OREAD(sc, OHCI_CYCLETIMER));
661}
662
663#define LAST_DB(dbtr, db) do { \
664 struct fwohcidb_tr *_dbtr = (dbtr); \
665 int _cnt = _dbtr->dbcnt; \
666 db = &_dbtr->db[ (_cnt > 2) ? (_cnt -1) : 0]; \
667} while (0)
668
669static void
670fwohci_start(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
671{
672 int i, s;
673 int tcode, hdr_len, hdr_off, len;
674 int fsegment = -1;
675 u_int32_t off;
676 struct fw_xfer *xfer;
677 struct fw_pkt *fp;
678 volatile struct fwohci_txpkthdr *ohcifp;
679 struct fwohcidb_tr *db_tr;
680 volatile struct fwohcidb *db;
681 struct mbuf *m;
682 struct tcode_info *info;
683
684 if(&sc->atrq == dbch){
685 off = OHCI_ATQOFF;
686 }else if(&sc->atrs == dbch){
687 off = OHCI_ATSOFF;
688 }else{
689 return;
690 }
691
692 if (dbch->flags & FWOHCI_DBCH_FULL)
693 return;
694
695 s = splfw();
696 db_tr = dbch->top;
697txloop:
698 xfer = STAILQ_FIRST(&dbch->xferq.q);
699 if(xfer == NULL){
700 goto kick;
701 }
702 if(dbch->xferq.queued == 0 ){
703 device_printf(sc->fc.dev, "TX queue empty\n");
704 }
705 STAILQ_REMOVE_HEAD(&dbch->xferq.q, link);
706 db_tr->xfer = xfer;
707 xfer->state = FWXF_START;
708 dbch->xferq.packets++;
709
710 fp = (struct fw_pkt *)(xfer->send.buf + xfer->send.off);
711 tcode = fp->mode.common.tcode;
712
713 ohcifp = (volatile struct fwohci_txpkthdr *) db_tr->db[1].db.immed;
714 info = &tinfo[tcode];
715 hdr_len = hdr_off = info->hdr_len;
716 /* fw_asyreq must pass valid send.len */
717 len = xfer->send.len;
718 for( i = 0 ; i < hdr_off ; i+= 4){
719 ohcifp->mode.ld[i/4] = ntohl(fp->mode.ld[i/4]);
720 }
721 ohcifp->mode.common.spd = xfer->spd;
722 if (tcode == FWTCODE_STREAM ){
723 hdr_len = 8;
724 ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
725 } else if (tcode == FWTCODE_PHY) {
726 hdr_len = 12;
727 ohcifp->mode.ld[1] = ntohl(fp->mode.ld[1]);
728 ohcifp->mode.ld[2] = ntohl(fp->mode.ld[2]);
729 ohcifp->mode.common.spd = 0;
730 ohcifp->mode.common.tcode = FWOHCITCODE_PHY;
731 } else {
732 ohcifp->mode.asycomm.dst = ntohs(fp->mode.hdr.dst);
733 ohcifp->mode.asycomm.srcbus = OHCI_ASYSRCBUS;
734 ohcifp->mode.asycomm.tlrt |= FWRETRY_X;
735 }
736 db = &db_tr->db[0];
737 db->db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | hdr_len;
738 db->db.desc.status = 0;
739/* Specify bound timer of asy. responce */
740 if(&sc->atrs == dbch){
741 db->db.desc.count
742 = (OREAD(sc, OHCI_CYCLETIMER) >> 12) + (1 << 13);
743 }
744
745 db_tr->dbcnt = 2;
746 db = &db_tr->db[db_tr->dbcnt];
747 if(len > hdr_off){
748 if (xfer->mbuf == NULL) {
749 db->db.desc.addr
750 = vtophys(xfer->send.buf + xfer->send.off) + hdr_off;
751 db->db.desc.cmd
752 = OHCI_OUTPUT_MORE | ((len - hdr_off) & 0xffff);
753 db->db.desc.status = 0;
754
755 db_tr->dbcnt++;
756 } else {
757 /* XXX we assume mbuf chain is shorter than ndesc */
758 m = xfer->mbuf;
759 do {
760 db->db.desc.addr
761 = vtophys(mtod(m, caddr_t));
762 db->db.desc.cmd = OHCI_OUTPUT_MORE | m->m_len;
763 db->db.desc.status = 0;
764 db++;
765 db_tr->dbcnt++;
766 m = m->m_next;
767 } while (m != NULL);
768 }
769 }
770 /* last db */
771 LAST_DB(db_tr, db);
772 db->db.desc.cmd |= OHCI_OUTPUT_LAST
773 | OHCI_INTERRUPT_ALWAYS
774 | OHCI_BRANCH_ALWAYS;
775 db->db.desc.depend = vtophys(STAILQ_NEXT(db_tr, link)->db);
776
777 if(fsegment == -1 )
778 fsegment = db_tr->dbcnt;
779 if (dbch->pdb_tr != NULL) {
780 LAST_DB(dbch->pdb_tr, db);
781 db->db.desc.depend |= db_tr->dbcnt;
782 }
783 dbch->pdb_tr = db_tr;
784 db_tr = STAILQ_NEXT(db_tr, link);
785 if(db_tr != dbch->bottom){
786 goto txloop;
787 } else {
784 printf("fwohci_start: lack of db_trq\n");
788 device_printf(sc->fc.dev, "fwohci_start: lack of db_trq\n");
785 dbch->flags |= FWOHCI_DBCH_FULL;
786 }
787kick:
788 if (firewire_debug) printf("kick\n");
789 /* kick asy q */
790
791 if(dbch->xferq.flag & FWXFERQ_RUNNING) {
792 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
793 } else {
789 dbch->flags |= FWOHCI_DBCH_FULL;
790 }
791kick:
792 if (firewire_debug) printf("kick\n");
793 /* kick asy q */
794
795 if(dbch->xferq.flag & FWXFERQ_RUNNING) {
796 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_WAKE);
797 } else {
794 printf("start AT DMA status=%x\n",
798 if (bootverbose)
799 device_printf(sc->fc.dev, "start AT DMA status=%x\n",
795 OREAD(sc, OHCI_DMACTL(off)));
796 OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | fsegment);
797 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
798 dbch->xferq.flag |= FWXFERQ_RUNNING;
799 }
800
801 dbch->top = db_tr;
802 splx(s);
803 return;
804}
805
806static void
807fwohci_drain_atq(struct firewire_comm *fc, struct fw_xfer *xfer)
808{
809 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
810 fwohci_drain(&sc->fc, xfer, &(sc->atrq));
811 return;
812}
813
814static void
815fwohci_drain_ats(struct firewire_comm *fc, struct fw_xfer *xfer)
816{
817 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
818 fwohci_drain(&sc->fc, xfer, &(sc->atrs));
819 return;
820}
821
822static void
823fwohci_start_atq(struct firewire_comm *fc)
824{
825 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
826 fwohci_start( sc, &(sc->atrq));
827 return;
828}
829
830static void
831fwohci_start_ats(struct firewire_comm *fc)
832{
833 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
834 fwohci_start( sc, &(sc->atrs));
835 return;
836}
837
838void
839fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
840{
841 int s, err = 0;
842 struct fwohcidb_tr *tr;
843 volatile struct fwohcidb *db;
844 struct fw_xfer *xfer;
845 u_int32_t off;
846 u_int stat;
847 int packets;
848 struct firewire_comm *fc = (struct firewire_comm *)sc;
849 if(&sc->atrq == dbch){
850 off = OHCI_ATQOFF;
851 }else if(&sc->atrs == dbch){
852 off = OHCI_ATSOFF;
853 }else{
854 return;
855 }
856 s = splfw();
857 tr = dbch->bottom;
858 packets = 0;
859 while(dbch->xferq.queued > 0){
860 LAST_DB(tr, db);
861 if(!(db->db.desc.status & OHCI_CNTL_DMA_ACTIVE)){
862 if (fc->status != FWBUSRESET)
863 /* maybe out of order?? */
864 goto out;
865 }
866 if(db->db.desc.status & OHCI_CNTL_DMA_DEAD) {
867#ifdef OHCI_DEBUG
868 dump_dma(sc, ch);
869 dump_db(sc, ch);
870#endif
871/* Stop DMA */
872 OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
873 device_printf(sc->fc.dev, "force reset AT FIFO\n");
874 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
875 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
876 OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
877 }
878 stat = db->db.desc.status & FWOHCIEV_MASK;
879 switch(stat){
880 case FWOHCIEV_ACKCOMPL:
881 case FWOHCIEV_ACKPEND:
882 err = 0;
883 break;
884 case FWOHCIEV_ACKBSA:
885 case FWOHCIEV_ACKBSB:
886 device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]);
887 case FWOHCIEV_ACKBSX:
888 err = EBUSY;
889 break;
890 case FWOHCIEV_FLUSHED:
891 case FWOHCIEV_ACKTARD:
892 device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]);
893 err = EAGAIN;
894 break;
895 case FWOHCIEV_MISSACK:
896 case FWOHCIEV_UNDRRUN:
897 case FWOHCIEV_OVRRUN:
898 case FWOHCIEV_DESCERR:
899 case FWOHCIEV_DTRDERR:
900 case FWOHCIEV_TIMEOUT:
901 case FWOHCIEV_TCODERR:
902 case FWOHCIEV_UNKNOWN:
903 case FWOHCIEV_ACKDERR:
904 case FWOHCIEV_ACKTERR:
905 default:
906 device_printf(sc->fc.dev, "txd err=%2x %s\n",
907 stat, fwohcicode[stat]);
908 err = EINVAL;
909 break;
910 }
911 if(tr->xfer != NULL){
912 xfer = tr->xfer;
913 xfer->state = FWXF_SENT;
914 if(err == EBUSY && fc->status != FWBUSRESET){
915 xfer->state = FWXF_BUSY;
916 switch(xfer->act_type){
917 case FWACT_XFER:
918 xfer->resp = err;
919 if(xfer->retry_req != NULL){
920 xfer->retry_req(xfer);
921 }
922 break;
923 default:
924 break;
925 }
926 } else if( stat != FWOHCIEV_ACKPEND){
927 if (stat != FWOHCIEV_ACKCOMPL)
928 xfer->state = FWXF_SENTERR;
929 xfer->resp = err;
930 switch(xfer->act_type){
931 case FWACT_XFER:
932 fw_xfer_done(xfer);
933 break;
934 default:
935 break;
936 }
937 }
938 dbch->xferq.queued --;
939 }
940 tr->xfer = NULL;
941
942 packets ++;
943 tr = STAILQ_NEXT(tr, link);
944 dbch->bottom = tr;
945 }
946out:
947 if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
948 printf("make free slot\n");
949 dbch->flags &= ~FWOHCI_DBCH_FULL;
950 fwohci_start(sc, dbch);
951 }
952 splx(s);
953}
954
955static void
956fwohci_drain(struct firewire_comm *fc, struct fw_xfer *xfer, struct fwohci_dbch *dbch)
957{
958 int i, s;
959 struct fwohcidb_tr *tr;
960
961 if(xfer->state != FWXF_START) return;
962
963 s = splfw();
964 tr = dbch->bottom;
965 for( i = 0 ; i <= dbch->xferq.queued ; i ++){
966 if(tr->xfer == xfer){
967 s = splfw();
968 tr->xfer = NULL;
969 dbch->xferq.queued --;
970#if 1
971 /* XXX */
972 if (tr == dbch->bottom)
973 dbch->bottom = STAILQ_NEXT(tr, link);
974#endif
975 if (dbch->flags & FWOHCI_DBCH_FULL) {
976 printf("fwohci_drain: make slot\n");
977 dbch->flags &= ~FWOHCI_DBCH_FULL;
978 fwohci_start((struct fwohci_softc *)fc, dbch);
979 }
980
981 splx(s);
982 break;
983 }
984 tr = STAILQ_NEXT(tr, link);
985 }
986 splx(s);
987 return;
988}
989
990static void
991fwohci_db_free(struct fwohci_dbch *dbch)
992{
993 struct fwohcidb_tr *db_tr;
994 int idb;
995
996 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
997 for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0;
998 idb < dbch->ndb;
999 db_tr = STAILQ_NEXT(db_tr, link), idb++){
1000 free(db_tr->buf, M_DEVBUF);
1001 db_tr->buf = NULL;
1002 }
1003 }
1004 dbch->ndb = 0;
1005 db_tr = STAILQ_FIRST(&dbch->db_trq);
1006 contigfree((void *)(uintptr_t)(volatile void *)db_tr->db,
1007 sizeof(struct fwohcidb) * dbch->ndesc * dbch->ndb, M_DEVBUF);
1008 /* Attach DB to DMA ch. */
1009 free(db_tr, M_DEVBUF);
1010 STAILQ_INIT(&dbch->db_trq);
1011}
1012
1013static void
1014fwohci_db_init(struct fwohci_dbch *dbch)
1015{
1016 int idb;
1017 struct fwohcidb *db;
1018 struct fwohcidb_tr *db_tr;
1019 /* allocate DB entries and attach one to each DMA channels */
1020 /* DB entry must start at 16 bytes bounary. */
1021 dbch->frag.buf = NULL;
1022 dbch->frag.len = 0;
1023 dbch->frag.plen = 0;
1024 dbch->xferq.queued = 0;
1025 dbch->pdb_tr = NULL;
1026
1027 STAILQ_INIT(&dbch->db_trq);
1028 db_tr = (struct fwohcidb_tr *)
1029 malloc(sizeof(struct fwohcidb_tr) * dbch->ndb,
1030 M_DEVBUF, M_DONTWAIT);
1031 if(db_tr == NULL){
1032 return;
1033 }
1034 db = (struct fwohcidb *)
1035 contigmalloc(sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb,
1036 M_DEVBUF, M_DONTWAIT, 0x10000, 0xffffffff, PAGE_SIZE, 0ul);
1037 if(db == NULL){
1038 printf("fwochi_db_init: contigmalloc failed\n");
1039 return;
1040 }
1041 bzero(db, sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb);
1042 /* Attach DB to DMA ch. */
1043 for(idb = 0 ; idb < dbch->ndb ; idb++){
1044 db_tr->dbcnt = 0;
1045 db_tr->db = &db[idb * dbch->ndesc];
1046 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1047 if(!(dbch->xferq.flag & FWXFERQ_PACKET) &&
1048 (idb % dbch->xferq.bnpacket == 0)){
1049 dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].start
1050 = (caddr_t)db_tr;
1051 }
1052 if((!(dbch->xferq.flag & FWXFERQ_PACKET)) &&
1053 ((idb + 1)% dbch->xferq.bnpacket == 0)){
1054 dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].end
1055 = (caddr_t)db_tr;
1056 }
1057 db_tr++;
1058 }
1059 STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
1060 = STAILQ_FIRST(&dbch->db_trq);
1061 dbch->top = STAILQ_FIRST(&dbch->db_trq);
1062 dbch->bottom = dbch->top;
1063}
1064
1065static int
1066fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1067{
1068 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1069 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1070 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1071 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1072 fwohci_db_free(&sc->it[dmach]);
1073 sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1074 return 0;
1075}
1076
1077static int
1078fwohci_irx_disable(struct firewire_comm *fc, int dmach)
1079{
1080 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1081
1082 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1083 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1084 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1085 if(sc->ir[dmach].dummy != NULL){
1086 free(sc->ir[dmach].dummy, M_DEVBUF);
1087 }
1088 sc->ir[dmach].dummy = NULL;
1089 fwohci_db_free(&sc->ir[dmach]);
1090 sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1091 return 0;
1092}
1093
1094static void
1095fwohci_irx_post (struct firewire_comm *fc , u_int32_t *qld)
1096{
1097 qld[0] = ntohl(qld[0]);
1098 return;
1099}
1100
1101static int
1102fwohci_irxpp_enable(struct firewire_comm *fc, int dmach)
1103{
1104 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1105 int err = 0;
1106 unsigned short tag, ich;
1107
1108 tag = (sc->ir[dmach].xferq.flag >> 6) & 3;
1109 ich = sc->ir[dmach].xferq.flag & 0x3f;
1110
1111#if 0
1112 if(STAILQ_FIRST(&fc->ir[dmach]->q) != NULL){
1113 wakeup(fc->ir[dmach]);
1114 return err;
1115 }
1116#endif
1117
1118 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1119 if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){
1120 sc->ir[dmach].xferq.queued = 0;
1121 sc->ir[dmach].ndb = NDB;
1122 sc->ir[dmach].xferq.psize = FWPMAX_S400;
1123 sc->ir[dmach].ndesc = 1;
1124 fwohci_db_init(&sc->ir[dmach]);
1125 err = fwohci_rx_enable(sc, &sc->ir[dmach]);
1126 }
1127 if(err){
1128 device_printf(sc->fc.dev, "err in IRX setting\n");
1129 return err;
1130 }
1131 if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){
1132 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1133 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1134 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1135 OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1136 OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf8000000);
1137 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1138 OWRITE(sc, OHCI_IRCMD(dmach),
1139 vtophys(sc->ir[dmach].top->db) | 1);
1140 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1141 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1142 }
1143 return err;
1144}
1145
1146static int
1147fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1148{
1149 int err = 0;
1150 int idb, z, i, dmach = 0;
1151 u_int32_t off = NULL;
1152 struct fwohcidb_tr *db_tr;
1153
1154 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1155 err = EINVAL;
1156 return err;
1157 }
1158 z = dbch->ndesc;
1159 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1160 if( &sc->it[dmach] == dbch){
1161 off = OHCI_ITOFF(dmach);
1162 break;
1163 }
1164 }
1165 if(off == NULL){
1166 err = EINVAL;
1167 return err;
1168 }
1169 if(dbch->xferq.flag & FWXFERQ_RUNNING)
1170 return err;
1171 dbch->xferq.flag |= FWXFERQ_RUNNING;
1172 for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
1173 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1174 }
1175 db_tr = dbch->top;
1176 for( idb = 0 ; idb < dbch->ndb ; idb ++){
1177 fwohci_add_tx_buf(db_tr,
1178 dbch->xferq.psize, dbch->xferq.flag,
1179 dbch->xferq.buf + dbch->xferq.psize * idb);
1180 if(STAILQ_NEXT(db_tr, link) == NULL){
1181 break;
1182 }
1183 db_tr->db[0].db.desc.depend
1184 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1185 db_tr->db[db_tr->dbcnt - 1].db.desc.depend
1186 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1187 if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1188 if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1189 db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
1190 |= OHCI_INTERRUPT_ALWAYS;
1191 db_tr->db[0].db.desc.depend &= ~0xf;
1192 db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
1193 ~0xf;
1194 }
1195 }
1196 db_tr = STAILQ_NEXT(db_tr, link);
1197 }
1198 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
1199 return err;
1200}
1201
1202static int
1203fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1204{
1205 int err = 0;
1206 int idb, z, i, dmach = 0;
1207 u_int32_t off = NULL;
1208 struct fwohcidb_tr *db_tr;
1209
1210 z = dbch->ndesc;
1211 if(&sc->arrq == dbch){
1212 off = OHCI_ARQOFF;
1213 }else if(&sc->arrs == dbch){
1214 off = OHCI_ARSOFF;
1215 }else{
1216 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1217 if( &sc->ir[dmach] == dbch){
1218 off = OHCI_IROFF(dmach);
1219 break;
1220 }
1221 }
1222 }
1223 if(off == NULL){
1224 err = EINVAL;
1225 return err;
1226 }
1227 if(dbch->xferq.flag & FWXFERQ_STREAM){
1228 if(dbch->xferq.flag & FWXFERQ_RUNNING)
1229 return err;
1230 }else{
1231 if(dbch->xferq.flag & FWXFERQ_RUNNING){
1232 err = EBUSY;
1233 return err;
1234 }
1235 }
1236 dbch->xferq.flag |= FWXFERQ_RUNNING;
1237 for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
1238 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1239 }
1240 db_tr = dbch->top;
1241 for( idb = 0 ; idb < dbch->ndb ; idb ++){
1242 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1243 fwohci_add_rx_buf(db_tr,
1244 dbch->xferq.psize, dbch->xferq.flag, 0, NULL);
1245 }else{
1246 fwohci_add_rx_buf(db_tr,
1247 dbch->xferq.psize, dbch->xferq.flag,
1248 dbch->xferq.buf + dbch->xferq.psize * idb,
1249 dbch->dummy + sizeof(u_int32_t) * idb);
1250 }
1251 if(STAILQ_NEXT(db_tr, link) == NULL){
1252 break;
1253 }
1254 db_tr->db[db_tr->dbcnt - 1].db.desc.depend
1255 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1256 if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1257 if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1258 db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
1259 |= OHCI_INTERRUPT_ALWAYS;
1260 db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
1261 ~0xf;
1262 }
1263 }
1264 db_tr = STAILQ_NEXT(db_tr, link);
1265 }
1266 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
1267 dbch->buf_offset = 0;
1268 if(dbch->xferq.flag & FWXFERQ_STREAM){
1269 return err;
1270 }else{
1271 OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | z);
1272 }
1273 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1274 return err;
1275}
1276
1277static int
1278fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
1279{
1280 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1281 int err = 0;
1282 unsigned short tag, ich;
1283 struct fwohci_dbch *dbch;
1284 struct fw_pkt *fp;
1285 struct fwohcidb_tr *db_tr;
1286
1287 tag = (sc->it[dmach].xferq.flag >> 6) & 3;
1288 ich = sc->it[dmach].xferq.flag & 0x3f;
1289 dbch = &sc->it[dmach];
1290 if(dbch->ndb == 0){
1291 dbch->xferq.queued = 0;
1292 dbch->ndb = dbch->xferq.bnpacket * dbch->xferq.bnchunk;
1293 dbch->ndesc = 3;
1294 fwohci_db_init(dbch);
1295 err = fwohci_tx_enable(sc, dbch);
1296 }
1297 if(err)
1298 return err;
1299 if(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){
1300 if(dbch->xferq.stdma2 != NULL){
1301 fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
1302 ((struct fwohcidb_tr *)
1303 (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
1304 |= OHCI_BRANCH_ALWAYS;
1305 ((struct fwohcidb_tr *)
1306 (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
1307 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1308 ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
1309 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1310 ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
1311 ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
1312 }
1313 }else if(!(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){
1314 fw_tbuf_update(&sc->fc, dmach, 0);
1315 if(dbch->xferq.stdma == NULL){
1316 return err;
1317 }
1318 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1319 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1320 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1321 OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1322 OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xf0000000);
1323 fwohci_txbufdb(sc, dmach, dbch->xferq.stdma);
1324 if(dbch->xferq.stdma2 != NULL){
1325 fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
1326 ((struct fwohcidb_tr *)
1327 (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
1328 |= OHCI_BRANCH_ALWAYS;
1329 ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
1330 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1331 ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
1332 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1333 ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
1334 ((struct fwohcidb_tr *) (dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
1335 }else{
1336 ((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
1337 ((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[0].db.desc.depend &= ~0xf;
1338 }
1339 OWRITE(sc, OHCI_ITCMD(dmach),
1340 vtophys(((struct fwohcidb_tr *)
1341 (dbch->xferq.stdma->start))->db) | dbch->ndesc);
1342 if(dbch->xferq.flag & FWXFERQ_DV){
1343 db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma->start;
1344 fp = (struct fw_pkt *)db_tr->buf;
1345 fp->mode.ld[2] = htonl(0x80000000 +
1346 ((fc->cyctimer(fc) + 0x3000) & 0xf000));
1347 }
1348
1349 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1350 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1351 }
1352 return err;
1353}
1354
1355static int
1356fwohci_irxbuf_enable(struct firewire_comm *fc, int dmach)
1357{
1358 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1359 int err = 0;
1360 unsigned short tag, ich;
1361 tag = (sc->ir[dmach].xferq.flag >> 6) & 3;
1362 ich = sc->ir[dmach].xferq.flag & 0x3f;
1363 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1364
1365 if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){
1366 sc->ir[dmach].xferq.queued = 0;
1367 sc->ir[dmach].ndb = sc->ir[dmach].xferq.bnpacket *
1368 sc->ir[dmach].xferq.bnchunk;
1369 sc->ir[dmach].dummy =
1370 malloc(sizeof(u_int32_t) * sc->ir[dmach].ndb,
1371 M_DEVBUF, M_DONTWAIT);
1372 if(sc->ir[dmach].dummy == NULL){
1373 err = ENOMEM;
1374 return err;
1375 }
1376 sc->ir[dmach].ndesc = 2;
1377 fwohci_db_init(&sc->ir[dmach]);
1378 err = fwohci_rx_enable(sc, &sc->ir[dmach]);
1379 }
1380 if(err)
1381 return err;
1382
1383 if(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){
1384 if(sc->ir[dmach].xferq.stdma2 != NULL){
1385 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
1386 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
1387 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
1388 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
1389 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
1390 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
1391 }
1392 }else if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)
1393 && !(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET)){
1394 fw_rbuf_update(&sc->fc, dmach, 0);
1395
1396 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1397 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1398 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1399 OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1400 OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1401 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1402 if(sc->ir[dmach].xferq.stdma2 != NULL){
1403 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
1404 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
1405 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
1406 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
1407 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
1408 }else{
1409 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
1410 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend &= ~0xf;
1411 }
1412 OWRITE(sc, OHCI_IRCMD(dmach),
1413 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->start))->db) | sc->ir[dmach].ndesc);
1414 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1415 }
1416 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1417 return err;
1418}
1419
1420static int
1421fwohci_irx_enable(struct firewire_comm *fc, int dmach)
1422{
1423 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1424 int err = 0;
1425
1426 if(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET){
1427 err = fwohci_irxpp_enable(fc, dmach);
1428 return err;
1429 }else{
1430 err = fwohci_irxbuf_enable(fc, dmach);
1431 return err;
1432 }
1433}
1434
1435int
1436fwohci_shutdown(device_t dev)
1437{
1438 u_int i;
1439 struct fwohci_softc *sc = device_get_softc(dev);
1440
1441/* Now stopping all DMA channel */
1442 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1443 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1444 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1445 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1446
1447 for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
1448 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1449 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1450 }
1451
1452/* FLUSH FIFO and reset Transmitter/Reciever */
1453 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1454
1455/* Stop interrupt */
1456 OWRITE(sc, FWOHCI_INTMASKCLR,
1457 OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1458 | OHCI_INT_PHY_INT
1459 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1460 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1461 | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1462 | OHCI_INT_PHY_BUS_R);
1463 return 0;
1464}
1465
1466#define ACK_ALL
1467static void
1468fwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count)
1469{
1470 u_int32_t irstat, itstat;
1471 u_int i;
1472 struct firewire_comm *fc = (struct firewire_comm *)sc;
1473
1474#ifdef OHCI_DEBUG
1475 if(stat & OREAD(sc, FWOHCI_INTMASK))
1476 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",
1477 stat & OHCI_INT_EN ? "DMA_EN ":"",
1478 stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1479 stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1480 stat & OHCI_INT_ERR ? "INT_ERR ":"",
1481 stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1482 stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1483 stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1484 stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1485 stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1486 stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1487 stat & OHCI_INT_PHY_SID ? "SID ":"",
1488 stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1489 stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1490 stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1491 stat & OHCI_INT_DMA_IT ? "DMA_IT " :"",
1492 stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"",
1493 stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"",
1494 stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"",
1495 stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"",
1496 stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"",
1497 stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"",
1498 stat, OREAD(sc, FWOHCI_INTMASK)
1499 );
1500#endif
1501/* Bus reset */
1502 if(stat & OHCI_INT_PHY_BUS_R ){
1503 device_printf(fc->dev, "BUS reset\n");
1504 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1505 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1506
1507 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1508 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1509 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1510 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1511
1512#if 0
1513 for( i = 0 ; i < fc->nisodma ; i ++ ){
1514 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1515 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1516 }
1517
1518#endif
1519 fw_busreset(fc);
1520
1521 /* XXX need to wait DMA to stop */
1522#ifndef ACK_ALL
1523 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1524#endif
1525#if 1
1526 /* pending all pre-bus_reset packets */
1527 fwohci_txd(sc, &sc->atrq);
1528 fwohci_txd(sc, &sc->atrs);
1529 fwohci_arcv(sc, &sc->arrs, -1);
1530 fwohci_arcv(sc, &sc->arrq, -1);
1531#endif
1532
1533
1534 OWRITE(sc, OHCI_AREQHI, 1 << 31);
1535 /* XXX insecure ?? */
1536 OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1537 OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1538 OWRITE(sc, OHCI_PREQUPPER, 0x10000);
1539
1540 }
1541 if((stat & OHCI_INT_DMA_IR )){
1542#ifndef ACK_ALL
1543 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IR);
1544#endif
1545 irstat = OREAD(sc, OHCI_IR_STAT);
1546 OWRITE(sc, OHCI_IR_STATCLR, ~0);
1547 for(i = 0; i < fc->nisodma ; i++){
1548 if((irstat & (1 << i)) != 0){
1549 if(sc->ir[i].xferq.flag & FWXFERQ_PACKET){
1550 fwohci_ircv(sc, &sc->ir[i], count);
1551 }else{
1552 fwohci_rbuf_update(sc, i);
1553 }
1554 }
1555 }
1556 }
1557 if((stat & OHCI_INT_DMA_IT )){
1558#ifndef ACK_ALL
1559 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IT);
1560#endif
1561 itstat = OREAD(sc, OHCI_IT_STAT);
1562 OWRITE(sc, OHCI_IT_STATCLR, ~0);
1563 for(i = 0; i < fc->nisodma ; i++){
1564 if((itstat & (1 << i)) != 0){
1565 fwohci_tbuf_update(sc, i);
1566 }
1567 }
1568 }
1569 if((stat & OHCI_INT_DMA_PRRS )){
1570#ifndef ACK_ALL
1571 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRS);
1572#endif
1573#if 0
1574 dump_dma(sc, ARRS_CH);
1575 dump_db(sc, ARRS_CH);
1576#endif
1577 fwohci_arcv(sc, &sc->arrs, count);
1578 }
1579 if((stat & OHCI_INT_DMA_PRRQ )){
1580#ifndef ACK_ALL
1581 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRQ);
1582#endif
1583#if 0
1584 dump_dma(sc, ARRQ_CH);
1585 dump_db(sc, ARRQ_CH);
1586#endif
1587 fwohci_arcv(sc, &sc->arrq, count);
1588 }
1589 if(stat & OHCI_INT_PHY_SID){
1590 caddr_t buf;
1591 int plen;
1592
1593#ifndef ACK_ALL
1594 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_SID);
1595#endif
1596/*
1597** Checking whether the node is root or not. If root, turn on
1598** cycle master.
1599*/
1600 device_printf(fc->dev, "node_id = 0x%08x, ", OREAD(sc, FWOHCI_NODEID));
1601 if(!(OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_VALID)){
1602 printf("Bus reset failure\n");
1603 goto sidout;
1604 }
1605 if( OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_ROOT ){
1606 printf("CYCLEMASTER mode\n");
1607 OWRITE(sc, OHCI_LNKCTL,
1608 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1609 }else{
1610 printf("non CYCLEMASTER mode\n");
1611 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1612 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1613 }
1614 fc->nodeid = OREAD(sc, FWOHCI_NODEID) & 0x3f;
1615
1616 plen = OREAD(sc, OHCI_SID_CNT) & OHCI_SID_CNT_MASK;
1617 plen -= 4; /* chop control info */
1618 buf = malloc( FWPMAX_S400, M_DEVBUF, M_NOWAIT);
1619 if(buf == NULL) goto sidout;
1620 bcopy((void *)(uintptr_t)(volatile void *)fc->sid_buf,
1621 buf, plen);
1622 fw_sidrcv(fc, buf, plen, 0);
1623 }
1624sidout:
1625 if((stat & OHCI_INT_DMA_ATRQ )){
1626#ifndef ACK_ALL
1627 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRQ);
1628#endif
1629 fwohci_txd(sc, &(sc->atrq));
1630 }
1631 if((stat & OHCI_INT_DMA_ATRS )){
1632#ifndef ACK_ALL
1633 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRS);
1634#endif
1635 fwohci_txd(sc, &(sc->atrs));
1636 }
1637 if((stat & OHCI_INT_PW_ERR )){
1638#ifndef ACK_ALL
1639 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PW_ERR);
1640#endif
1641 device_printf(fc->dev, "posted write error\n");
1642 }
1643 if((stat & OHCI_INT_ERR )){
1644#ifndef ACK_ALL
1645 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_ERR);
1646#endif
1647 device_printf(fc->dev, "unrecoverable error\n");
1648 }
1649 if((stat & OHCI_INT_PHY_INT)) {
1650#ifndef ACK_ALL
1651 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_INT);
1652#endif
1653 device_printf(fc->dev, "phy int\n");
1654 }
1655
1656 return;
1657}
1658
1659void
1660fwohci_intr(void *arg)
1661{
1662 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1663 u_int32_t stat;
1664
1665 if (!(sc->intmask & OHCI_INT_EN)) {
1666 /* polling mode */
1667 return;
1668 }
1669
1670 while ((stat = OREAD(sc, FWOHCI_INTSTAT)) != 0) {
1671 if (stat == 0xffffffff) {
1672 device_printf(sc->fc.dev,
1673 "device physically ejected?\n");
1674 return;
1675 }
1676#ifdef ACK_ALL
1677 OWRITE(sc, FWOHCI_INTSTATCLR, stat);
1678#endif
1679 fwohci_intr_body(sc, stat, -1);
1680 }
1681}
1682
1683static void
1684fwohci_poll(struct firewire_comm *fc, int quick, int count)
1685{
1686 int s;
1687 u_int32_t stat;
1688 struct fwohci_softc *sc;
1689
1690
1691 sc = (struct fwohci_softc *)fc;
1692 stat = OHCI_INT_DMA_IR | OHCI_INT_DMA_IT |
1693 OHCI_INT_DMA_PRRS | OHCI_INT_DMA_PRRQ |
1694 OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS;
1695#if 0
1696 if (!quick) {
1697#else
1698 if (1) {
1699#endif
1700 stat = OREAD(sc, FWOHCI_INTSTAT);
1701 if (stat == 0)
1702 return;
1703 if (stat == 0xffffffff) {
1704 device_printf(sc->fc.dev,
1705 "device physically ejected?\n");
1706 return;
1707 }
1708#ifdef ACK_ALL
1709 OWRITE(sc, FWOHCI_INTSTATCLR, stat);
1710#endif
1711 }
1712 s = splfw();
1713 fwohci_intr_body(sc, stat, count);
1714 splx(s);
1715}
1716
1717static void
1718fwohci_set_intr(struct firewire_comm *fc, int enable)
1719{
1720 struct fwohci_softc *sc;
1721
1722 sc = (struct fwohci_softc *)fc;
800 OREAD(sc, OHCI_DMACTL(off)));
801 OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | fsegment);
802 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
803 dbch->xferq.flag |= FWXFERQ_RUNNING;
804 }
805
806 dbch->top = db_tr;
807 splx(s);
808 return;
809}
810
811static void
812fwohci_drain_atq(struct firewire_comm *fc, struct fw_xfer *xfer)
813{
814 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
815 fwohci_drain(&sc->fc, xfer, &(sc->atrq));
816 return;
817}
818
819static void
820fwohci_drain_ats(struct firewire_comm *fc, struct fw_xfer *xfer)
821{
822 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
823 fwohci_drain(&sc->fc, xfer, &(sc->atrs));
824 return;
825}
826
827static void
828fwohci_start_atq(struct firewire_comm *fc)
829{
830 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
831 fwohci_start( sc, &(sc->atrq));
832 return;
833}
834
835static void
836fwohci_start_ats(struct firewire_comm *fc)
837{
838 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
839 fwohci_start( sc, &(sc->atrs));
840 return;
841}
842
843void
844fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
845{
846 int s, err = 0;
847 struct fwohcidb_tr *tr;
848 volatile struct fwohcidb *db;
849 struct fw_xfer *xfer;
850 u_int32_t off;
851 u_int stat;
852 int packets;
853 struct firewire_comm *fc = (struct firewire_comm *)sc;
854 if(&sc->atrq == dbch){
855 off = OHCI_ATQOFF;
856 }else if(&sc->atrs == dbch){
857 off = OHCI_ATSOFF;
858 }else{
859 return;
860 }
861 s = splfw();
862 tr = dbch->bottom;
863 packets = 0;
864 while(dbch->xferq.queued > 0){
865 LAST_DB(tr, db);
866 if(!(db->db.desc.status & OHCI_CNTL_DMA_ACTIVE)){
867 if (fc->status != FWBUSRESET)
868 /* maybe out of order?? */
869 goto out;
870 }
871 if(db->db.desc.status & OHCI_CNTL_DMA_DEAD) {
872#ifdef OHCI_DEBUG
873 dump_dma(sc, ch);
874 dump_db(sc, ch);
875#endif
876/* Stop DMA */
877 OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
878 device_printf(sc->fc.dev, "force reset AT FIFO\n");
879 OWRITE(sc, OHCI_HCCCTLCLR, OHCI_HCC_LINKEN);
880 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS | OHCI_HCC_LINKEN);
881 OWRITE(sc, OHCI_DMACTLCLR(off), OHCI_CNTL_DMA_RUN);
882 }
883 stat = db->db.desc.status & FWOHCIEV_MASK;
884 switch(stat){
885 case FWOHCIEV_ACKCOMPL:
886 case FWOHCIEV_ACKPEND:
887 err = 0;
888 break;
889 case FWOHCIEV_ACKBSA:
890 case FWOHCIEV_ACKBSB:
891 device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]);
892 case FWOHCIEV_ACKBSX:
893 err = EBUSY;
894 break;
895 case FWOHCIEV_FLUSHED:
896 case FWOHCIEV_ACKTARD:
897 device_printf(sc->fc.dev, "txd err=%2x %s\n", stat, fwohcicode[stat]);
898 err = EAGAIN;
899 break;
900 case FWOHCIEV_MISSACK:
901 case FWOHCIEV_UNDRRUN:
902 case FWOHCIEV_OVRRUN:
903 case FWOHCIEV_DESCERR:
904 case FWOHCIEV_DTRDERR:
905 case FWOHCIEV_TIMEOUT:
906 case FWOHCIEV_TCODERR:
907 case FWOHCIEV_UNKNOWN:
908 case FWOHCIEV_ACKDERR:
909 case FWOHCIEV_ACKTERR:
910 default:
911 device_printf(sc->fc.dev, "txd err=%2x %s\n",
912 stat, fwohcicode[stat]);
913 err = EINVAL;
914 break;
915 }
916 if(tr->xfer != NULL){
917 xfer = tr->xfer;
918 xfer->state = FWXF_SENT;
919 if(err == EBUSY && fc->status != FWBUSRESET){
920 xfer->state = FWXF_BUSY;
921 switch(xfer->act_type){
922 case FWACT_XFER:
923 xfer->resp = err;
924 if(xfer->retry_req != NULL){
925 xfer->retry_req(xfer);
926 }
927 break;
928 default:
929 break;
930 }
931 } else if( stat != FWOHCIEV_ACKPEND){
932 if (stat != FWOHCIEV_ACKCOMPL)
933 xfer->state = FWXF_SENTERR;
934 xfer->resp = err;
935 switch(xfer->act_type){
936 case FWACT_XFER:
937 fw_xfer_done(xfer);
938 break;
939 default:
940 break;
941 }
942 }
943 dbch->xferq.queued --;
944 }
945 tr->xfer = NULL;
946
947 packets ++;
948 tr = STAILQ_NEXT(tr, link);
949 dbch->bottom = tr;
950 }
951out:
952 if ((dbch->flags & FWOHCI_DBCH_FULL) && packets > 0) {
953 printf("make free slot\n");
954 dbch->flags &= ~FWOHCI_DBCH_FULL;
955 fwohci_start(sc, dbch);
956 }
957 splx(s);
958}
959
960static void
961fwohci_drain(struct firewire_comm *fc, struct fw_xfer *xfer, struct fwohci_dbch *dbch)
962{
963 int i, s;
964 struct fwohcidb_tr *tr;
965
966 if(xfer->state != FWXF_START) return;
967
968 s = splfw();
969 tr = dbch->bottom;
970 for( i = 0 ; i <= dbch->xferq.queued ; i ++){
971 if(tr->xfer == xfer){
972 s = splfw();
973 tr->xfer = NULL;
974 dbch->xferq.queued --;
975#if 1
976 /* XXX */
977 if (tr == dbch->bottom)
978 dbch->bottom = STAILQ_NEXT(tr, link);
979#endif
980 if (dbch->flags & FWOHCI_DBCH_FULL) {
981 printf("fwohci_drain: make slot\n");
982 dbch->flags &= ~FWOHCI_DBCH_FULL;
983 fwohci_start((struct fwohci_softc *)fc, dbch);
984 }
985
986 splx(s);
987 break;
988 }
989 tr = STAILQ_NEXT(tr, link);
990 }
991 splx(s);
992 return;
993}
994
995static void
996fwohci_db_free(struct fwohci_dbch *dbch)
997{
998 struct fwohcidb_tr *db_tr;
999 int idb;
1000
1001 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1002 for(db_tr = STAILQ_FIRST(&dbch->db_trq), idb = 0;
1003 idb < dbch->ndb;
1004 db_tr = STAILQ_NEXT(db_tr, link), idb++){
1005 free(db_tr->buf, M_DEVBUF);
1006 db_tr->buf = NULL;
1007 }
1008 }
1009 dbch->ndb = 0;
1010 db_tr = STAILQ_FIRST(&dbch->db_trq);
1011 contigfree((void *)(uintptr_t)(volatile void *)db_tr->db,
1012 sizeof(struct fwohcidb) * dbch->ndesc * dbch->ndb, M_DEVBUF);
1013 /* Attach DB to DMA ch. */
1014 free(db_tr, M_DEVBUF);
1015 STAILQ_INIT(&dbch->db_trq);
1016}
1017
1018static void
1019fwohci_db_init(struct fwohci_dbch *dbch)
1020{
1021 int idb;
1022 struct fwohcidb *db;
1023 struct fwohcidb_tr *db_tr;
1024 /* allocate DB entries and attach one to each DMA channels */
1025 /* DB entry must start at 16 bytes bounary. */
1026 dbch->frag.buf = NULL;
1027 dbch->frag.len = 0;
1028 dbch->frag.plen = 0;
1029 dbch->xferq.queued = 0;
1030 dbch->pdb_tr = NULL;
1031
1032 STAILQ_INIT(&dbch->db_trq);
1033 db_tr = (struct fwohcidb_tr *)
1034 malloc(sizeof(struct fwohcidb_tr) * dbch->ndb,
1035 M_DEVBUF, M_DONTWAIT);
1036 if(db_tr == NULL){
1037 return;
1038 }
1039 db = (struct fwohcidb *)
1040 contigmalloc(sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb,
1041 M_DEVBUF, M_DONTWAIT, 0x10000, 0xffffffff, PAGE_SIZE, 0ul);
1042 if(db == NULL){
1043 printf("fwochi_db_init: contigmalloc failed\n");
1044 return;
1045 }
1046 bzero(db, sizeof (struct fwohcidb) * dbch->ndesc * dbch->ndb);
1047 /* Attach DB to DMA ch. */
1048 for(idb = 0 ; idb < dbch->ndb ; idb++){
1049 db_tr->dbcnt = 0;
1050 db_tr->db = &db[idb * dbch->ndesc];
1051 STAILQ_INSERT_TAIL(&dbch->db_trq, db_tr, link);
1052 if(!(dbch->xferq.flag & FWXFERQ_PACKET) &&
1053 (idb % dbch->xferq.bnpacket == 0)){
1054 dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].start
1055 = (caddr_t)db_tr;
1056 }
1057 if((!(dbch->xferq.flag & FWXFERQ_PACKET)) &&
1058 ((idb + 1)% dbch->xferq.bnpacket == 0)){
1059 dbch->xferq.bulkxfer[idb/dbch->xferq.bnpacket].end
1060 = (caddr_t)db_tr;
1061 }
1062 db_tr++;
1063 }
1064 STAILQ_LAST(&dbch->db_trq, fwohcidb_tr,link)->link.stqe_next
1065 = STAILQ_FIRST(&dbch->db_trq);
1066 dbch->top = STAILQ_FIRST(&dbch->db_trq);
1067 dbch->bottom = dbch->top;
1068}
1069
1070static int
1071fwohci_itx_disable(struct firewire_comm *fc, int dmach)
1072{
1073 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1074 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1075 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1076 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1077 fwohci_db_free(&sc->it[dmach]);
1078 sc->it[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1079 return 0;
1080}
1081
1082static int
1083fwohci_irx_disable(struct firewire_comm *fc, int dmach)
1084{
1085 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1086
1087 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1088 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1089 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1090 if(sc->ir[dmach].dummy != NULL){
1091 free(sc->ir[dmach].dummy, M_DEVBUF);
1092 }
1093 sc->ir[dmach].dummy = NULL;
1094 fwohci_db_free(&sc->ir[dmach]);
1095 sc->ir[dmach].xferq.flag &= ~FWXFERQ_RUNNING;
1096 return 0;
1097}
1098
1099static void
1100fwohci_irx_post (struct firewire_comm *fc , u_int32_t *qld)
1101{
1102 qld[0] = ntohl(qld[0]);
1103 return;
1104}
1105
1106static int
1107fwohci_irxpp_enable(struct firewire_comm *fc, int dmach)
1108{
1109 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1110 int err = 0;
1111 unsigned short tag, ich;
1112
1113 tag = (sc->ir[dmach].xferq.flag >> 6) & 3;
1114 ich = sc->ir[dmach].xferq.flag & 0x3f;
1115
1116#if 0
1117 if(STAILQ_FIRST(&fc->ir[dmach]->q) != NULL){
1118 wakeup(fc->ir[dmach]);
1119 return err;
1120 }
1121#endif
1122
1123 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1124 if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){
1125 sc->ir[dmach].xferq.queued = 0;
1126 sc->ir[dmach].ndb = NDB;
1127 sc->ir[dmach].xferq.psize = FWPMAX_S400;
1128 sc->ir[dmach].ndesc = 1;
1129 fwohci_db_init(&sc->ir[dmach]);
1130 err = fwohci_rx_enable(sc, &sc->ir[dmach]);
1131 }
1132 if(err){
1133 device_printf(sc->fc.dev, "err in IRX setting\n");
1134 return err;
1135 }
1136 if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){
1137 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1138 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1139 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1140 OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1141 OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf8000000);
1142 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1143 OWRITE(sc, OHCI_IRCMD(dmach),
1144 vtophys(sc->ir[dmach].top->db) | 1);
1145 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1146 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1147 }
1148 return err;
1149}
1150
1151static int
1152fwohci_tx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1153{
1154 int err = 0;
1155 int idb, z, i, dmach = 0;
1156 u_int32_t off = NULL;
1157 struct fwohcidb_tr *db_tr;
1158
1159 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1160 err = EINVAL;
1161 return err;
1162 }
1163 z = dbch->ndesc;
1164 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1165 if( &sc->it[dmach] == dbch){
1166 off = OHCI_ITOFF(dmach);
1167 break;
1168 }
1169 }
1170 if(off == NULL){
1171 err = EINVAL;
1172 return err;
1173 }
1174 if(dbch->xferq.flag & FWXFERQ_RUNNING)
1175 return err;
1176 dbch->xferq.flag |= FWXFERQ_RUNNING;
1177 for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
1178 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1179 }
1180 db_tr = dbch->top;
1181 for( idb = 0 ; idb < dbch->ndb ; idb ++){
1182 fwohci_add_tx_buf(db_tr,
1183 dbch->xferq.psize, dbch->xferq.flag,
1184 dbch->xferq.buf + dbch->xferq.psize * idb);
1185 if(STAILQ_NEXT(db_tr, link) == NULL){
1186 break;
1187 }
1188 db_tr->db[0].db.desc.depend
1189 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1190 db_tr->db[db_tr->dbcnt - 1].db.desc.depend
1191 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1192 if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1193 if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1194 db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
1195 |= OHCI_INTERRUPT_ALWAYS;
1196 db_tr->db[0].db.desc.depend &= ~0xf;
1197 db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
1198 ~0xf;
1199 }
1200 }
1201 db_tr = STAILQ_NEXT(db_tr, link);
1202 }
1203 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
1204 return err;
1205}
1206
1207static int
1208fwohci_rx_enable(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
1209{
1210 int err = 0;
1211 int idb, z, i, dmach = 0;
1212 u_int32_t off = NULL;
1213 struct fwohcidb_tr *db_tr;
1214
1215 z = dbch->ndesc;
1216 if(&sc->arrq == dbch){
1217 off = OHCI_ARQOFF;
1218 }else if(&sc->arrs == dbch){
1219 off = OHCI_ARSOFF;
1220 }else{
1221 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
1222 if( &sc->ir[dmach] == dbch){
1223 off = OHCI_IROFF(dmach);
1224 break;
1225 }
1226 }
1227 }
1228 if(off == NULL){
1229 err = EINVAL;
1230 return err;
1231 }
1232 if(dbch->xferq.flag & FWXFERQ_STREAM){
1233 if(dbch->xferq.flag & FWXFERQ_RUNNING)
1234 return err;
1235 }else{
1236 if(dbch->xferq.flag & FWXFERQ_RUNNING){
1237 err = EBUSY;
1238 return err;
1239 }
1240 }
1241 dbch->xferq.flag |= FWXFERQ_RUNNING;
1242 for( i = 0, dbch->bottom = dbch->top; i < (dbch->ndb - 1); i++){
1243 dbch->bottom = STAILQ_NEXT(dbch->bottom, link);
1244 }
1245 db_tr = dbch->top;
1246 for( idb = 0 ; idb < dbch->ndb ; idb ++){
1247 if(!(dbch->xferq.flag & FWXFERQ_EXTBUF)){
1248 fwohci_add_rx_buf(db_tr,
1249 dbch->xferq.psize, dbch->xferq.flag, 0, NULL);
1250 }else{
1251 fwohci_add_rx_buf(db_tr,
1252 dbch->xferq.psize, dbch->xferq.flag,
1253 dbch->xferq.buf + dbch->xferq.psize * idb,
1254 dbch->dummy + sizeof(u_int32_t) * idb);
1255 }
1256 if(STAILQ_NEXT(db_tr, link) == NULL){
1257 break;
1258 }
1259 db_tr->db[db_tr->dbcnt - 1].db.desc.depend
1260 = vtophys(STAILQ_NEXT(db_tr, link)->db) | z;
1261 if(dbch->xferq.flag & FWXFERQ_EXTBUF){
1262 if(((idb + 1 ) % dbch->xferq.bnpacket) == 0){
1263 db_tr->db[db_tr->dbcnt - 1].db.desc.cmd
1264 |= OHCI_INTERRUPT_ALWAYS;
1265 db_tr->db[db_tr->dbcnt - 1].db.desc.depend &=
1266 ~0xf;
1267 }
1268 }
1269 db_tr = STAILQ_NEXT(db_tr, link);
1270 }
1271 dbch->bottom->db[db_tr->dbcnt - 1].db.desc.depend &= 0xfffffff0;
1272 dbch->buf_offset = 0;
1273 if(dbch->xferq.flag & FWXFERQ_STREAM){
1274 return err;
1275 }else{
1276 OWRITE(sc, OHCI_DMACMD(off), vtophys(dbch->top->db) | z);
1277 }
1278 OWRITE(sc, OHCI_DMACTL(off), OHCI_CNTL_DMA_RUN);
1279 return err;
1280}
1281
1282static int
1283fwohci_itxbuf_enable(struct firewire_comm *fc, int dmach)
1284{
1285 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1286 int err = 0;
1287 unsigned short tag, ich;
1288 struct fwohci_dbch *dbch;
1289 struct fw_pkt *fp;
1290 struct fwohcidb_tr *db_tr;
1291
1292 tag = (sc->it[dmach].xferq.flag >> 6) & 3;
1293 ich = sc->it[dmach].xferq.flag & 0x3f;
1294 dbch = &sc->it[dmach];
1295 if(dbch->ndb == 0){
1296 dbch->xferq.queued = 0;
1297 dbch->ndb = dbch->xferq.bnpacket * dbch->xferq.bnchunk;
1298 dbch->ndesc = 3;
1299 fwohci_db_init(dbch);
1300 err = fwohci_tx_enable(sc, dbch);
1301 }
1302 if(err)
1303 return err;
1304 if(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){
1305 if(dbch->xferq.stdma2 != NULL){
1306 fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
1307 ((struct fwohcidb_tr *)
1308 (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
1309 |= OHCI_BRANCH_ALWAYS;
1310 ((struct fwohcidb_tr *)
1311 (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
1312 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1313 ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
1314 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1315 ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
1316 ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
1317 }
1318 }else if(!(OREAD(sc, OHCI_ITCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)){
1319 fw_tbuf_update(&sc->fc, dmach, 0);
1320 if(dbch->xferq.stdma == NULL){
1321 return err;
1322 }
1323 OWRITE(sc, OHCI_ITCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1324 OWRITE(sc, OHCI_IT_MASKCLR, 1 << dmach);
1325 OWRITE(sc, OHCI_IT_STATCLR, 1 << dmach);
1326 OWRITE(sc, OHCI_IT_MASK, 1 << dmach);
1327 OWRITE(sc, OHCI_ITCTLCLR(dmach), 0xf0000000);
1328 fwohci_txbufdb(sc, dmach, dbch->xferq.stdma);
1329 if(dbch->xferq.stdma2 != NULL){
1330 fwohci_txbufdb(sc, dmach, dbch->xferq.stdma2);
1331 ((struct fwohcidb_tr *)
1332 (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.cmd
1333 |= OHCI_BRANCH_ALWAYS;
1334 ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend =
1335 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1336 ((struct fwohcidb_tr *)(dbch->xferq.stdma->end))->db[0].db.desc.depend =
1337 vtophys(((struct fwohcidb_tr *)(dbch->xferq.stdma2->start))->db) | dbch->ndesc;
1338 ((struct fwohcidb_tr *)(dbch->xferq.stdma2->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
1339 ((struct fwohcidb_tr *) (dbch->xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
1340 }else{
1341 ((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
1342 ((struct fwohcidb_tr *) (dbch->xferq.stdma->end))->db[0].db.desc.depend &= ~0xf;
1343 }
1344 OWRITE(sc, OHCI_ITCMD(dmach),
1345 vtophys(((struct fwohcidb_tr *)
1346 (dbch->xferq.stdma->start))->db) | dbch->ndesc);
1347 if(dbch->xferq.flag & FWXFERQ_DV){
1348 db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma->start;
1349 fp = (struct fw_pkt *)db_tr->buf;
1350 fp->mode.ld[2] = htonl(0x80000000 +
1351 ((fc->cyctimer(fc) + 0x3000) & 0xf000));
1352 }
1353
1354 OWRITE(sc, OHCI_ITCTL(dmach), OHCI_CNTL_DMA_RUN);
1355 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IT);
1356 }
1357 return err;
1358}
1359
1360static int
1361fwohci_irxbuf_enable(struct firewire_comm *fc, int dmach)
1362{
1363 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1364 int err = 0;
1365 unsigned short tag, ich;
1366 tag = (sc->ir[dmach].xferq.flag >> 6) & 3;
1367 ich = sc->ir[dmach].xferq.flag & 0x3f;
1368 OWRITE(sc, OHCI_IRMATCH(dmach), tagbit[tag] | ich);
1369
1370 if(!(sc->ir[dmach].xferq.flag & FWXFERQ_RUNNING)){
1371 sc->ir[dmach].xferq.queued = 0;
1372 sc->ir[dmach].ndb = sc->ir[dmach].xferq.bnpacket *
1373 sc->ir[dmach].xferq.bnchunk;
1374 sc->ir[dmach].dummy =
1375 malloc(sizeof(u_int32_t) * sc->ir[dmach].ndb,
1376 M_DEVBUF, M_DONTWAIT);
1377 if(sc->ir[dmach].dummy == NULL){
1378 err = ENOMEM;
1379 return err;
1380 }
1381 sc->ir[dmach].ndesc = 2;
1382 fwohci_db_init(&sc->ir[dmach]);
1383 err = fwohci_rx_enable(sc, &sc->ir[dmach]);
1384 }
1385 if(err)
1386 return err;
1387
1388 if(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE){
1389 if(sc->ir[dmach].xferq.stdma2 != NULL){
1390 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
1391 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
1392 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
1393 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
1394 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
1395 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[0].db.desc.depend &= ~0xf;
1396 }
1397 }else if(!(OREAD(sc, OHCI_IRCTL(dmach)) & OHCI_CNTL_DMA_ACTIVE)
1398 && !(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET)){
1399 fw_rbuf_update(&sc->fc, dmach, 0);
1400
1401 OWRITE(sc, OHCI_IRCTLCLR(dmach), OHCI_CNTL_DMA_RUN);
1402 OWRITE(sc, OHCI_IR_MASKCLR, 1 << dmach);
1403 OWRITE(sc, OHCI_IR_STATCLR, 1 << dmach);
1404 OWRITE(sc, OHCI_IR_MASK, 1 << dmach);
1405 OWRITE(sc, OHCI_IRCTLCLR(dmach), 0xf0000000);
1406 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_ISOHDR);
1407 if(sc->ir[dmach].xferq.stdma2 != NULL){
1408 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend =
1409 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db) | sc->ir[dmach].ndesc;
1410 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend =
1411 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->start))->db);
1412 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma2->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
1413 }else{
1414 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[sc->ir[dmach].ndesc - 1].db.desc.depend &= ~0xf;
1415 ((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->end))->db[0].db.desc.depend &= ~0xf;
1416 }
1417 OWRITE(sc, OHCI_IRCMD(dmach),
1418 vtophys(((struct fwohcidb_tr *)(sc->ir[dmach].xferq.stdma->start))->db) | sc->ir[dmach].ndesc);
1419 OWRITE(sc, OHCI_IRCTL(dmach), OHCI_CNTL_DMA_RUN);
1420 }
1421 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_DMA_IR);
1422 return err;
1423}
1424
1425static int
1426fwohci_irx_enable(struct firewire_comm *fc, int dmach)
1427{
1428 struct fwohci_softc *sc = (struct fwohci_softc *)fc;
1429 int err = 0;
1430
1431 if(sc->ir[dmach].xferq.flag & FWXFERQ_PACKET){
1432 err = fwohci_irxpp_enable(fc, dmach);
1433 return err;
1434 }else{
1435 err = fwohci_irxbuf_enable(fc, dmach);
1436 return err;
1437 }
1438}
1439
1440int
1441fwohci_shutdown(device_t dev)
1442{
1443 u_int i;
1444 struct fwohci_softc *sc = device_get_softc(dev);
1445
1446/* Now stopping all DMA channel */
1447 OWRITE(sc, OHCI_ARQCTLCLR, OHCI_CNTL_DMA_RUN);
1448 OWRITE(sc, OHCI_ARSCTLCLR, OHCI_CNTL_DMA_RUN);
1449 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1450 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1451
1452 for( i = 0 ; i < sc->fc.nisodma ; i ++ ){
1453 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1454 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1455 }
1456
1457/* FLUSH FIFO and reset Transmitter/Reciever */
1458 OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_RESET);
1459
1460/* Stop interrupt */
1461 OWRITE(sc, FWOHCI_INTMASKCLR,
1462 OHCI_INT_EN | OHCI_INT_ERR | OHCI_INT_PHY_SID
1463 | OHCI_INT_PHY_INT
1464 | OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS
1465 | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
1466 | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
1467 | OHCI_INT_PHY_BUS_R);
1468 return 0;
1469}
1470
1471#define ACK_ALL
1472static void
1473fwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count)
1474{
1475 u_int32_t irstat, itstat;
1476 u_int i;
1477 struct firewire_comm *fc = (struct firewire_comm *)sc;
1478
1479#ifdef OHCI_DEBUG
1480 if(stat & OREAD(sc, FWOHCI_INTMASK))
1481 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",
1482 stat & OHCI_INT_EN ? "DMA_EN ":"",
1483 stat & OHCI_INT_PHY_REG ? "PHY_REG ":"",
1484 stat & OHCI_INT_CYC_LONG ? "CYC_LONG ":"",
1485 stat & OHCI_INT_ERR ? "INT_ERR ":"",
1486 stat & OHCI_INT_CYC_ERR ? "CYC_ERR ":"",
1487 stat & OHCI_INT_CYC_LOST ? "CYC_LOST ":"",
1488 stat & OHCI_INT_CYC_64SECOND ? "CYC_64SECOND ":"",
1489 stat & OHCI_INT_CYC_START ? "CYC_START ":"",
1490 stat & OHCI_INT_PHY_INT ? "PHY_INT ":"",
1491 stat & OHCI_INT_PHY_BUS_R ? "BUS_RESET ":"",
1492 stat & OHCI_INT_PHY_SID ? "SID ":"",
1493 stat & OHCI_INT_LR_ERR ? "DMA_LR_ERR ":"",
1494 stat & OHCI_INT_PW_ERR ? "DMA_PW_ERR ":"",
1495 stat & OHCI_INT_DMA_IR ? "DMA_IR ":"",
1496 stat & OHCI_INT_DMA_IT ? "DMA_IT " :"",
1497 stat & OHCI_INT_DMA_PRRS ? "DMA_PRRS " :"",
1498 stat & OHCI_INT_DMA_PRRQ ? "DMA_PRRQ " :"",
1499 stat & OHCI_INT_DMA_ARRS ? "DMA_ARRS " :"",
1500 stat & OHCI_INT_DMA_ARRQ ? "DMA_ARRQ " :"",
1501 stat & OHCI_INT_DMA_ATRS ? "DMA_ATRS " :"",
1502 stat & OHCI_INT_DMA_ATRQ ? "DMA_ATRQ " :"",
1503 stat, OREAD(sc, FWOHCI_INTMASK)
1504 );
1505#endif
1506/* Bus reset */
1507 if(stat & OHCI_INT_PHY_BUS_R ){
1508 device_printf(fc->dev, "BUS reset\n");
1509 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
1510 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
1511
1512 OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN);
1513 sc->atrq.xferq.flag &= ~FWXFERQ_RUNNING;
1514 OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
1515 sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
1516
1517#if 0
1518 for( i = 0 ; i < fc->nisodma ; i ++ ){
1519 OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
1520 OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
1521 }
1522
1523#endif
1524 fw_busreset(fc);
1525
1526 /* XXX need to wait DMA to stop */
1527#ifndef ACK_ALL
1528 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
1529#endif
1530#if 1
1531 /* pending all pre-bus_reset packets */
1532 fwohci_txd(sc, &sc->atrq);
1533 fwohci_txd(sc, &sc->atrs);
1534 fwohci_arcv(sc, &sc->arrs, -1);
1535 fwohci_arcv(sc, &sc->arrq, -1);
1536#endif
1537
1538
1539 OWRITE(sc, OHCI_AREQHI, 1 << 31);
1540 /* XXX insecure ?? */
1541 OWRITE(sc, OHCI_PREQHI, 0x7fffffff);
1542 OWRITE(sc, OHCI_PREQLO, 0xffffffff);
1543 OWRITE(sc, OHCI_PREQUPPER, 0x10000);
1544
1545 }
1546 if((stat & OHCI_INT_DMA_IR )){
1547#ifndef ACK_ALL
1548 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IR);
1549#endif
1550 irstat = OREAD(sc, OHCI_IR_STAT);
1551 OWRITE(sc, OHCI_IR_STATCLR, ~0);
1552 for(i = 0; i < fc->nisodma ; i++){
1553 if((irstat & (1 << i)) != 0){
1554 if(sc->ir[i].xferq.flag & FWXFERQ_PACKET){
1555 fwohci_ircv(sc, &sc->ir[i], count);
1556 }else{
1557 fwohci_rbuf_update(sc, i);
1558 }
1559 }
1560 }
1561 }
1562 if((stat & OHCI_INT_DMA_IT )){
1563#ifndef ACK_ALL
1564 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_IT);
1565#endif
1566 itstat = OREAD(sc, OHCI_IT_STAT);
1567 OWRITE(sc, OHCI_IT_STATCLR, ~0);
1568 for(i = 0; i < fc->nisodma ; i++){
1569 if((itstat & (1 << i)) != 0){
1570 fwohci_tbuf_update(sc, i);
1571 }
1572 }
1573 }
1574 if((stat & OHCI_INT_DMA_PRRS )){
1575#ifndef ACK_ALL
1576 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRS);
1577#endif
1578#if 0
1579 dump_dma(sc, ARRS_CH);
1580 dump_db(sc, ARRS_CH);
1581#endif
1582 fwohci_arcv(sc, &sc->arrs, count);
1583 }
1584 if((stat & OHCI_INT_DMA_PRRQ )){
1585#ifndef ACK_ALL
1586 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_PRRQ);
1587#endif
1588#if 0
1589 dump_dma(sc, ARRQ_CH);
1590 dump_db(sc, ARRQ_CH);
1591#endif
1592 fwohci_arcv(sc, &sc->arrq, count);
1593 }
1594 if(stat & OHCI_INT_PHY_SID){
1595 caddr_t buf;
1596 int plen;
1597
1598#ifndef ACK_ALL
1599 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_SID);
1600#endif
1601/*
1602** Checking whether the node is root or not. If root, turn on
1603** cycle master.
1604*/
1605 device_printf(fc->dev, "node_id = 0x%08x, ", OREAD(sc, FWOHCI_NODEID));
1606 if(!(OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_VALID)){
1607 printf("Bus reset failure\n");
1608 goto sidout;
1609 }
1610 if( OREAD(sc, FWOHCI_NODEID) & OHCI_NODE_ROOT ){
1611 printf("CYCLEMASTER mode\n");
1612 OWRITE(sc, OHCI_LNKCTL,
1613 OHCI_CNTL_CYCMTR | OHCI_CNTL_CYCTIMER);
1614 }else{
1615 printf("non CYCLEMASTER mode\n");
1616 OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCMTR);
1617 OWRITE(sc, OHCI_LNKCTL, OHCI_CNTL_CYCTIMER);
1618 }
1619 fc->nodeid = OREAD(sc, FWOHCI_NODEID) & 0x3f;
1620
1621 plen = OREAD(sc, OHCI_SID_CNT) & OHCI_SID_CNT_MASK;
1622 plen -= 4; /* chop control info */
1623 buf = malloc( FWPMAX_S400, M_DEVBUF, M_NOWAIT);
1624 if(buf == NULL) goto sidout;
1625 bcopy((void *)(uintptr_t)(volatile void *)fc->sid_buf,
1626 buf, plen);
1627 fw_sidrcv(fc, buf, plen, 0);
1628 }
1629sidout:
1630 if((stat & OHCI_INT_DMA_ATRQ )){
1631#ifndef ACK_ALL
1632 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRQ);
1633#endif
1634 fwohci_txd(sc, &(sc->atrq));
1635 }
1636 if((stat & OHCI_INT_DMA_ATRS )){
1637#ifndef ACK_ALL
1638 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_DMA_ATRS);
1639#endif
1640 fwohci_txd(sc, &(sc->atrs));
1641 }
1642 if((stat & OHCI_INT_PW_ERR )){
1643#ifndef ACK_ALL
1644 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PW_ERR);
1645#endif
1646 device_printf(fc->dev, "posted write error\n");
1647 }
1648 if((stat & OHCI_INT_ERR )){
1649#ifndef ACK_ALL
1650 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_ERR);
1651#endif
1652 device_printf(fc->dev, "unrecoverable error\n");
1653 }
1654 if((stat & OHCI_INT_PHY_INT)) {
1655#ifndef ACK_ALL
1656 OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_INT);
1657#endif
1658 device_printf(fc->dev, "phy int\n");
1659 }
1660
1661 return;
1662}
1663
1664void
1665fwohci_intr(void *arg)
1666{
1667 struct fwohci_softc *sc = (struct fwohci_softc *)arg;
1668 u_int32_t stat;
1669
1670 if (!(sc->intmask & OHCI_INT_EN)) {
1671 /* polling mode */
1672 return;
1673 }
1674
1675 while ((stat = OREAD(sc, FWOHCI_INTSTAT)) != 0) {
1676 if (stat == 0xffffffff) {
1677 device_printf(sc->fc.dev,
1678 "device physically ejected?\n");
1679 return;
1680 }
1681#ifdef ACK_ALL
1682 OWRITE(sc, FWOHCI_INTSTATCLR, stat);
1683#endif
1684 fwohci_intr_body(sc, stat, -1);
1685 }
1686}
1687
1688static void
1689fwohci_poll(struct firewire_comm *fc, int quick, int count)
1690{
1691 int s;
1692 u_int32_t stat;
1693 struct fwohci_softc *sc;
1694
1695
1696 sc = (struct fwohci_softc *)fc;
1697 stat = OHCI_INT_DMA_IR | OHCI_INT_DMA_IT |
1698 OHCI_INT_DMA_PRRS | OHCI_INT_DMA_PRRQ |
1699 OHCI_INT_DMA_ATRQ | OHCI_INT_DMA_ATRS;
1700#if 0
1701 if (!quick) {
1702#else
1703 if (1) {
1704#endif
1705 stat = OREAD(sc, FWOHCI_INTSTAT);
1706 if (stat == 0)
1707 return;
1708 if (stat == 0xffffffff) {
1709 device_printf(sc->fc.dev,
1710 "device physically ejected?\n");
1711 return;
1712 }
1713#ifdef ACK_ALL
1714 OWRITE(sc, FWOHCI_INTSTATCLR, stat);
1715#endif
1716 }
1717 s = splfw();
1718 fwohci_intr_body(sc, stat, count);
1719 splx(s);
1720}
1721
1722static void
1723fwohci_set_intr(struct firewire_comm *fc, int enable)
1724{
1725 struct fwohci_softc *sc;
1726
1727 sc = (struct fwohci_softc *)fc;
1723 printf("fwochi_set_intr: %d\n", enable);
1728 if (bootverbose)
1729 device_printf(sc->fc.dev, "fwochi_set_intr: %d\n", enable);
1724 if (enable) {
1725 sc->intmask |= OHCI_INT_EN;
1726 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
1727 } else {
1728 sc->intmask &= ~OHCI_INT_EN;
1729 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
1730 }
1731}
1732
1733static void
1734fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
1735{
1736 int stat;
1737 struct firewire_comm *fc = &sc->fc;
1738 struct fw_pkt *fp;
1739 struct fwohci_dbch *dbch;
1740 struct fwohcidb_tr *db_tr;
1741
1742 dbch = &sc->it[dmach];
1743 if((dbch->xferq.flag & FWXFERQ_DV) && (dbch->xferq.stdma2 != NULL)){
1744 db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma2->start;
1745/*
1746 * Overwrite highest significant 4 bits timestamp information
1747 */
1748 fp = (struct fw_pkt *)db_tr->buf;
1749 fp->mode.ld[2] |= htonl(0x80000000 |
1750 ((fc->cyctimer(fc) + 0x4000) & 0xf000));
1751 }
1752 stat = OREAD(sc, OHCI_ITCTL(dmach)) & 0x1f;
1753 switch(stat){
1754 case FWOHCIEV_ACKCOMPL:
1755 fw_tbuf_update(fc, dmach, 1);
1756 break;
1757 default:
1758 fw_tbuf_update(fc, dmach, 0);
1759 break;
1760 }
1761 fwohci_itxbuf_enable(&sc->fc, dmach);
1762}
1763
1764static void
1765fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
1766{
1767 int stat;
1768 stat = OREAD(sc, OHCI_IRCTL(dmach)) & 0x1f;
1769 switch(stat){
1770 case FWOHCIEV_ACKCOMPL:
1771 fw_rbuf_update(&sc->fc, dmach, 1);
1772 wakeup(sc->fc.ir[dmach]);
1773 fwohci_irx_enable(&sc->fc, dmach);
1774 break;
1775 default:
1776 break;
1777 }
1778}
1779
1780void
1781dump_dma(struct fwohci_softc *sc, u_int32_t ch)
1782{
1783 u_int32_t off, cntl, stat, cmd, match;
1784
1785 if(ch == 0){
1786 off = OHCI_ATQOFF;
1787 }else if(ch == 1){
1788 off = OHCI_ATSOFF;
1789 }else if(ch == 2){
1790 off = OHCI_ARQOFF;
1791 }else if(ch == 3){
1792 off = OHCI_ARSOFF;
1793 }else if(ch < IRX_CH){
1794 off = OHCI_ITCTL(ch - ITX_CH);
1795 }else{
1796 off = OHCI_IRCTL(ch - IRX_CH);
1797 }
1798 cntl = stat = OREAD(sc, off);
1799 cmd = OREAD(sc, off + 0xc);
1800 match = OREAD(sc, off + 0x10);
1801
1802 device_printf(sc->fc.dev, "dma ch %1x:dma regs 0x%08x 0x%08x 0x%08x 0x%08x \n",
1803 ch,
1804 cntl,
1805 stat,
1806 cmd,
1807 match);
1808 stat &= 0xffff ;
1809 if(stat & 0xff00){
1810 device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
1811 ch,
1812 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
1813 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
1814 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
1815 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
1816 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
1817 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
1818 fwohcicode[stat & 0x1f],
1819 stat & 0x1f
1820 );
1821 }else{
1822 device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
1823 }
1824}
1825
1826void
1827dump_db(struct fwohci_softc *sc, u_int32_t ch)
1828{
1829 struct fwohci_dbch *dbch;
1830 struct fwohcidb_tr *cp = NULL, *pp, *np;
1831 volatile struct fwohcidb *curr = NULL, *prev, *next = NULL;
1832 int idb, jdb;
1833 u_int32_t cmd, off;
1834 if(ch == 0){
1835 off = OHCI_ATQOFF;
1836 dbch = &sc->atrq;
1837 }else if(ch == 1){
1838 off = OHCI_ATSOFF;
1839 dbch = &sc->atrs;
1840 }else if(ch == 2){
1841 off = OHCI_ARQOFF;
1842 dbch = &sc->arrq;
1843 }else if(ch == 3){
1844 off = OHCI_ARSOFF;
1845 dbch = &sc->arrs;
1846 }else if(ch < IRX_CH){
1847 off = OHCI_ITCTL(ch - ITX_CH);
1848 dbch = &sc->it[ch - ITX_CH];
1849 }else {
1850 off = OHCI_IRCTL(ch - IRX_CH);
1851 dbch = &sc->ir[ch - IRX_CH];
1852 }
1853 cmd = OREAD(sc, off + 0xc);
1854
1855 if( dbch->ndb == 0 ){
1856 device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
1857 return;
1858 }
1859 pp = dbch->top;
1860 prev = pp->db;
1861 for(idb = 0 ; idb < dbch->ndb ; idb ++ ){
1862 if(pp == NULL){
1863 curr = NULL;
1864 goto outdb;
1865 }
1866 cp = STAILQ_NEXT(pp, link);
1867 if(cp == NULL){
1868 curr = NULL;
1869 goto outdb;
1870 }
1871 np = STAILQ_NEXT(cp, link);
1872 if(cp == NULL) break;
1873 for(jdb = 0 ; jdb < dbch->ndesc ; jdb ++ ){
1874 if((cmd & 0xfffffff0)
1875 == vtophys(&(cp->db[jdb]))){
1876 curr = cp->db;
1877 if(np != NULL){
1878 next = np->db;
1879 }else{
1880 next = NULL;
1881 }
1882 goto outdb;
1883 }
1884 }
1885 pp = STAILQ_NEXT(pp, link);
1886 prev = pp->db;
1887 }
1888outdb:
1889 if( curr != NULL){
1890 printf("Prev DB %d\n", ch);
1891 print_db(prev, ch, dbch->ndesc);
1892 printf("Current DB %d\n", ch);
1893 print_db(curr, ch, dbch->ndesc);
1894 printf("Next DB %d\n", ch);
1895 print_db(next, ch, dbch->ndesc);
1896 }else{
1897 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
1898 }
1899 return;
1900}
1901
1902void
1903print_db(volatile struct fwohcidb *db, u_int32_t ch, u_int32_t max)
1904{
1905 fwohcireg_t stat;
1906 int i, key;
1907
1908 if(db == NULL){
1909 printf("No Descriptor is found\n");
1910 return;
1911 }
1912
1913 printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
1914 ch,
1915 "Current",
1916 "OP ",
1917 "KEY",
1918 "INT",
1919 "BR ",
1920 "len",
1921 "Addr",
1922 "Depend",
1923 "Stat",
1924 "Cnt");
1925 for( i = 0 ; i <= max ; i ++){
1926 key = db[i].db.desc.cmd & OHCI_KEY_MASK;
1927 printf("%08tx %s %s %s %s %5d %08x %08x %04x:%04x",
1928 vtophys(&db[i]),
1929 dbcode[(db[i].db.desc.cmd >> 28) & 0xf],
1930 dbkey[(db[i].db.desc.cmd >> 24) & 0x7],
1931 dbcond[(db[i].db.desc.cmd >> 20) & 0x3],
1932 dbcond[(db[i].db.desc.cmd >> 18) & 0x3],
1933 db[i].db.desc.cmd & 0xffff,
1934 db[i].db.desc.addr,
1935 db[i].db.desc.depend,
1936 db[i].db.desc.status,
1937 db[i].db.desc.count);
1938 stat = db[i].db.desc.status;
1939 if(stat & 0xff00){
1940 printf(" %s%s%s%s%s%s %s(%x)\n",
1941 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
1942 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
1943 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
1944 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
1945 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
1946 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
1947 fwohcicode[stat & 0x1f],
1948 stat & 0x1f
1949 );
1950 }else{
1951 printf(" Nostat\n");
1952 }
1953 if(key == OHCI_KEY_ST2 ){
1954 printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
1955 db[i+1].db.immed[0],
1956 db[i+1].db.immed[1],
1957 db[i+1].db.immed[2],
1958 db[i+1].db.immed[3]);
1959 }
1960 if(key == OHCI_KEY_DEVICE){
1961 return;
1962 }
1963 if((db[i].db.desc.cmd & OHCI_BRANCH_MASK)
1964 == OHCI_BRANCH_ALWAYS){
1965 return;
1966 }
1967 if((db[i].db.desc.cmd & OHCI_CMD_MASK)
1968 == OHCI_OUTPUT_LAST){
1969 return;
1970 }
1971 if((db[i].db.desc.cmd & OHCI_CMD_MASK)
1972 == OHCI_INPUT_LAST){
1973 return;
1974 }
1975 if(key == OHCI_KEY_ST2 ){
1976 i++;
1977 }
1978 }
1979 return;
1980}
1981
1982void
1983fwohci_ibr(struct firewire_comm *fc)
1984{
1985 struct fwohci_softc *sc;
1986 u_int32_t fun;
1987
1988 sc = (struct fwohci_softc *)fc;
1989#if 1
1990 fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
1991 fun |= FW_PHY_IBR;
1992 fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
1993#else
1994 fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
1995 fun |= FW_PHY_ISBR;
1996 fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
1997#endif
1998}
1999
2000void
2001fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2002{
2003 struct fwohcidb_tr *db_tr, *fdb_tr;
2004 struct fwohci_dbch *dbch;
2005 struct fw_pkt *fp;
2006 volatile struct fwohci_txpkthdr *ohcifp;
2007 unsigned short chtag;
2008 int idb;
2009
2010 dbch = &sc->it[dmach];
2011 chtag = sc->it[dmach].xferq.flag & 0xff;
2012
2013 db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2014 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2015/*
2016device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), vtophys(fdb_tr->db));
2017*/
2018 if(bulkxfer->flag != 0){
2019 return;
2020 }
2021 bulkxfer->flag = 1;
2022 for( idb = 0 ; idb < bulkxfer->npacket ; idb ++){
2023 db_tr->db[0].db.desc.cmd
2024 = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
2025 fp = (struct fw_pkt *)db_tr->buf;
2026 ohcifp = (volatile struct fwohci_txpkthdr *)
2027 db_tr->db[1].db.immed;
2028 ohcifp->mode.ld[0] = ntohl(fp->mode.ld[0]);
2029 ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
2030 ohcifp->mode.stream.chtag = chtag;
2031 ohcifp->mode.stream.tcode = 0xa;
2032 ohcifp->mode.stream.spd = 4;
2033 ohcifp->mode.ld[2] = ntohl(fp->mode.ld[1]);
2034 ohcifp->mode.ld[3] = ntohl(fp->mode.ld[2]);
2035
2036 db_tr->db[2].db.desc.cmd
2037 = OHCI_OUTPUT_LAST
2038 | OHCI_UPDATE
2039 | OHCI_BRANCH_ALWAYS
2040 | ((ntohs(fp->mode.stream.len) ) & 0xffff);
2041 db_tr->db[2].db.desc.status = 0;
2042 db_tr->db[2].db.desc.count = 0;
2043 if(dbch->xferq.flag & FWXFERQ_DV){
2044 db_tr->db[0].db.desc.depend
2045 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2046 db_tr->db[dbch->ndesc - 1].db.desc.depend
2047 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2048 }else{
2049 db_tr->db[0].db.desc.depend
2050 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2051 db_tr->db[dbch->ndesc - 1].db.desc.depend
2052 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2053 }
2054 bulkxfer->end = (caddr_t)db_tr;
2055 db_tr = STAILQ_NEXT(db_tr, link);
2056 }
2057 db_tr = (struct fwohcidb_tr *)bulkxfer->end;
2058 db_tr->db[0].db.desc.depend &= ~0xf;
2059 db_tr->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
2060/**/
2061 db_tr->db[dbch->ndesc - 1].db.desc.cmd &= ~OHCI_BRANCH_ALWAYS;
2062 db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_BRANCH_NEVER;
2063/**/
2064 db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS;
2065
2066 db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2067 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2068/*
2069device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, vtophys(db_tr->db), vtophys(fdb_tr->db));
2070*/
2071 return;
2072}
2073
2074static int
2075fwohci_add_tx_buf(struct fwohcidb_tr *db_tr, unsigned short size,
2076 int mode, void *buf)
2077{
2078 volatile struct fwohcidb *db = db_tr->db;
2079 int err = 0;
2080 if(buf == 0){
2081 err = EINVAL;
2082 return err;
2083 }
2084 db_tr->buf = buf;
2085 db_tr->dbcnt = 3;
2086 db_tr->dummy = NULL;
2087
2088 db[0].db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
2089
2090 db[2].db.desc.depend = 0;
2091 db[2].db.desc.addr = vtophys(buf) + sizeof(u_int32_t);
2092 db[2].db.desc.cmd = OHCI_OUTPUT_MORE;
2093
2094 db[0].db.desc.status = 0;
2095 db[0].db.desc.count = 0;
2096
2097 db[2].db.desc.status = 0;
2098 db[2].db.desc.count = 0;
2099 if( mode & FWXFERQ_STREAM ){
2100 db[2].db.desc.cmd |= OHCI_OUTPUT_LAST;
2101 if(mode & FWXFERQ_PACKET ){
2102 db[2].db.desc.cmd
2103 |= OHCI_INTERRUPT_ALWAYS;
2104 }
2105 }
2106 db[2].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
2107 return 1;
2108}
2109
2110int
2111fwohci_add_rx_buf(struct fwohcidb_tr *db_tr, unsigned short size, int mode,
2112 void *buf, void *dummy)
2113{
2114 volatile struct fwohcidb *db = db_tr->db;
2115 int i;
2116 void *dbuf[2];
2117 int dsiz[2];
2118
2119 if(buf == 0){
2120 buf = malloc(size, M_DEVBUF, M_NOWAIT);
2121 if(buf == NULL) return 0;
2122 db_tr->buf = buf;
2123 db_tr->dbcnt = 1;
2124 db_tr->dummy = NULL;
2125 dsiz[0] = size;
2126 dbuf[0] = buf;
2127 }else if(dummy == NULL){
2128 db_tr->buf = buf;
2129 db_tr->dbcnt = 1;
2130 db_tr->dummy = NULL;
2131 dsiz[0] = size;
2132 dbuf[0] = buf;
2133 }else{
2134 db_tr->buf = buf;
2135 db_tr->dbcnt = 2;
2136 db_tr->dummy = dummy;
2137 dsiz[0] = sizeof(u_int32_t);
2138 dsiz[1] = size;
2139 dbuf[0] = dummy;
2140 dbuf[1] = buf;
2141 }
2142 for(i = 0 ; i < db_tr->dbcnt ; i++){
2143 db[i].db.desc.addr = vtophys(dbuf[i]) ;
2144 db[i].db.desc.cmd = OHCI_INPUT_MORE | dsiz[i];
2145 if( mode & FWXFERQ_STREAM ){
2146 db[i].db.desc.cmd |= OHCI_UPDATE;
2147 }
2148 db[i].db.desc.status = 0;
2149 db[i].db.desc.count = dsiz[i];
2150 }
2151 if( mode & FWXFERQ_STREAM ){
2152 db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_INPUT_LAST;
2153 if(mode & FWXFERQ_PACKET ){
2154 db[db_tr->dbcnt - 1].db.desc.cmd
2155 |= OHCI_INTERRUPT_ALWAYS;
2156 }
2157 }
2158 db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
2159 return 1;
2160}
2161
2162static void
2163fwohci_ircv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2164{
2165 struct fwohcidb_tr *db_tr = dbch->top, *odb_tr;
2166 struct firewire_comm *fc = (struct firewire_comm *)sc;
2167 int z = 1;
2168 struct fw_pkt *fp;
2169 u_int8_t *ld;
2170 u_int32_t off = NULL;
2171 u_int32_t stat;
2172 u_int32_t *qld;
2173 u_int32_t reg;
2174 u_int spd;
2175 u_int dmach;
2176 int len, i, plen;
2177 caddr_t buf;
2178
2179 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
2180 if( &sc->ir[dmach] == dbch){
2181 off = OHCI_IROFF(dmach);
2182 break;
2183 }
2184 }
2185 if(off == NULL){
2186 return;
2187 }
2188 if(!(dbch->xferq.flag & FWXFERQ_RUNNING)){
2189 fwohci_irx_disable(&sc->fc, dmach);
2190 return;
2191 }
2192
2193 odb_tr = NULL;
2194 db_tr = dbch->top;
2195 i = 0;
2196 while ((reg = db_tr->db[0].db.desc.status) & 0x1f) {
2197 if (count >= 0 && count-- == 0)
2198 break;
2199 ld = (u_int8_t *)db_tr->buf;
2200 if (dbch->xferq.flag & FWXFERQ_PACKET) {
2201 /* skip timeStamp */
2202 ld += sizeof(struct fwohci_trailer);
2203 }
2204 qld = (u_int32_t *)ld;
2205 len = dbch->xferq.psize - (db_tr->db[0].db.desc.count);
2206/*
2207{
2208device_printf(sc->fc.dev, "%04x %2x 0x%08x 0x%08x 0x%08x 0x%08x\n", len,
2209 db_tr->db[0].db.desc.status & 0x1f, qld[0],qld[1],qld[2],qld[3]);
2210}
2211*/
2212 fp=(struct fw_pkt *)ld;
2213 qld[0] = htonl(qld[0]);
2214 plen = sizeof(struct fw_isohdr)
2215 + ntohs(fp->mode.stream.len) + sizeof(u_int32_t);
2216 ld += plen;
2217 len -= plen;
2218 buf = db_tr->buf;
2219 db_tr->buf = NULL;
2220 stat = reg & 0x1f;
2221 spd = reg & 0x3;
2222 switch(stat){
2223 case FWOHCIEV_ACKCOMPL:
2224 case FWOHCIEV_ACKPEND:
2225 fw_rcv(&sc->fc, buf, plen - sizeof(u_int32_t), dmach, sizeof(u_int32_t), spd);
2226 break;
2227 default:
2228 free(buf, M_DEVBUF);
2229 device_printf(sc->fc.dev, "Isochronous receive err %02x\n", stat);
2230 break;
2231 }
2232 i++;
2233 fwohci_add_rx_buf(db_tr, dbch->xferq.psize,
2234 dbch->xferq.flag, 0, NULL);
2235 db_tr->db[0].db.desc.depend &= ~0xf;
2236 if(dbch->pdb_tr != NULL){
2237 dbch->pdb_tr->db[0].db.desc.depend |= z;
2238 } else {
2239 /* XXX should be rewritten in better way */
2240 dbch->bottom->db[0].db.desc.depend |= z;
2241 }
2242 dbch->pdb_tr = db_tr;
2243 db_tr = STAILQ_NEXT(db_tr, link);
2244 }
2245 dbch->top = db_tr;
2246 reg = OREAD(sc, OHCI_DMACTL(off));
2247 if (reg & OHCI_CNTL_DMA_ACTIVE)
2248 return;
2249 device_printf(sc->fc.dev, "IR DMA %d stopped at %x status=%x (%d)\n",
2250 dmach, OREAD(sc, OHCI_DMACMD(off)), reg, i);
2251 dbch->top = db_tr;
2252 fwohci_irx_enable(fc, dmach);
2253}
2254
2255#define PLEN(x) (((ntohs(x))+0x3) & ~0x3)
2256static int
2257fwohci_get_plen(struct fwohci_softc *sc, struct fw_pkt *fp, int hlen)
2258{
2259 int i;
2260
2261 for( i = 4; i < hlen ; i+=4){
2262 fp->mode.ld[i/4] = htonl(fp->mode.ld[i/4]);
2263 }
2264
2265 switch(fp->mode.common.tcode){
2266 case FWTCODE_RREQQ:
2267 return sizeof(fp->mode.rreqq) + sizeof(u_int32_t);
2268 case FWTCODE_WRES:
2269 return sizeof(fp->mode.wres) + sizeof(u_int32_t);
2270 case FWTCODE_WREQQ:
2271 return sizeof(fp->mode.wreqq) + sizeof(u_int32_t);
2272 case FWTCODE_RREQB:
2273 return sizeof(fp->mode.rreqb) + sizeof(u_int32_t);
2274 case FWTCODE_RRESQ:
2275 return sizeof(fp->mode.rresq) + sizeof(u_int32_t);
2276 case FWTCODE_WREQB:
2277 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.wreqb.len)
2278 + sizeof(u_int32_t);
2279 case FWTCODE_LREQ:
2280 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lreq.len)
2281 + sizeof(u_int32_t);
2282 case FWTCODE_RRESB:
2283 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.rresb.len)
2284 + sizeof(u_int32_t);
2285 case FWTCODE_LRES:
2286 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lres.len)
2287 + sizeof(u_int32_t);
2288 case FWOHCITCODE_PHY:
2289 return 16;
2290 }
2291 device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode);
2292 return 0;
2293}
2294
2295static void
2296fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2297{
2298 struct fwohcidb_tr *db_tr;
2299 int z = 1;
2300 struct fw_pkt *fp;
2301 u_int8_t *ld;
2302 u_int32_t stat, off;
2303 u_int spd;
2304 int len, plen, hlen, pcnt, poff = 0, rlen;
2305 int s;
2306 caddr_t buf;
2307 int resCount;
2308
2309 if(&sc->arrq == dbch){
2310 off = OHCI_ARQOFF;
2311 }else if(&sc->arrs == dbch){
2312 off = OHCI_ARSOFF;
2313 }else{
2314 return;
2315 }
2316
2317 s = splfw();
2318 db_tr = dbch->top;
2319 pcnt = 0;
2320 /* XXX we cannot handle a packet which lies in more than two buf */
2321 while (db_tr->db[0].db.desc.status & OHCI_CNTL_DMA_ACTIVE) {
2322 ld = (u_int8_t *)db_tr->buf + dbch->buf_offset;
2323 resCount = db_tr->db[0].db.desc.count;
2324 len = dbch->xferq.psize - resCount
2325 - dbch->buf_offset;
2326 while (len > 0 ) {
2327 if (count >= 0 && count-- == 0)
2328 goto out;
2329 if(dbch->frag.buf != NULL){
2330 buf = dbch->frag.buf;
2331 if (dbch->frag.plen < 0) {
2332 /* incomplete header */
2333 int hlen;
2334
2335 hlen = - dbch->frag.plen;
2336 rlen = hlen - dbch->frag.len;
2337 bcopy(ld, dbch->frag.buf + dbch->frag.len, rlen);
2338 ld += rlen;
2339 len -= rlen;
2340 dbch->frag.len += rlen;
2341#if 0
2342 printf("(1)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len);
2343#endif
2344 fp=(struct fw_pkt *)dbch->frag.buf;
2345 dbch->frag.plen
2346 = fwohci_get_plen(sc, fp, hlen);
2347 if (dbch->frag.plen == 0)
2348 goto out;
2349 }
2350 rlen = dbch->frag.plen - dbch->frag.len;
2351#if 0
2352 printf("(2)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len);
2353#endif
2354 bcopy(ld, dbch->frag.buf + dbch->frag.len,
2355 rlen);
2356 ld += rlen;
2357 len -= rlen;
2358 plen = dbch->frag.plen;
2359 dbch->frag.buf = NULL;
2360 dbch->frag.plen = 0;
2361 dbch->frag.len = 0;
2362 poff = 0;
2363 }else{
2364 fp=(struct fw_pkt *)ld;
2365 fp->mode.ld[0] = htonl(fp->mode.ld[0]);
2366 switch(fp->mode.common.tcode){
2367 case FWTCODE_RREQQ:
2368 case FWTCODE_WRES:
2369 case FWTCODE_WREQQ:
2370 case FWTCODE_RRESQ:
2371 case FWOHCITCODE_PHY:
2372 hlen = 12;
2373 break;
2374 case FWTCODE_RREQB:
2375 case FWTCODE_WREQB:
2376 case FWTCODE_LREQ:
2377 case FWTCODE_RRESB:
2378 case FWTCODE_LRES:
2379 hlen = 16;
2380 break;
2381 default:
2382 device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode);
2383 goto out;
2384 }
2385 if (len >= hlen) {
2386 plen = fwohci_get_plen(sc, fp, hlen);
2387 if (plen == 0)
2388 goto out;
2389 plen = (plen + 3) & ~3;
2390 len -= plen;
2391 } else {
2392 plen = -hlen;
2393 len -= hlen;
2394 }
2395 if(resCount > 0 || len > 0){
2396 buf = malloc( dbch->xferq.psize,
2397 M_DEVBUF, M_NOWAIT);
2398 if(buf == NULL){
2399 printf("cannot malloc!\n");
2400 free(db_tr->buf, M_DEVBUF);
2401 goto out;
2402 }
2403 bcopy(ld, buf, plen);
2404 poff = 0;
2405 dbch->frag.buf = NULL;
2406 dbch->frag.plen = 0;
2407 dbch->frag.len = 0;
2408 }else if(len < 0){
2409 dbch->frag.buf = db_tr->buf;
2410 if (plen < 0) {
2411#if 0
2412 printf("plen < 0:"
2413 "hlen: %d len: %d\n",
2414 hlen, len);
2415#endif
2416 dbch->frag.len = hlen + len;
2417 dbch->frag.plen = -hlen;
2418 } else {
2419 dbch->frag.len = plen + len;
2420 dbch->frag.plen = plen;
2421 }
2422 bcopy(ld, db_tr->buf, dbch->frag.len);
2423 buf = NULL;
2424 }else{
2425 buf = db_tr->buf;
2426 poff = ld - (u_int8_t *)buf;
2427 dbch->frag.buf = NULL;
2428 dbch->frag.plen = 0;
2429 dbch->frag.len = 0;
2430 }
2431 ld += plen;
2432 }
2433 if( buf != NULL){
2434/* DMA result-code will be written at the tail of packet */
2435 stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat;
2436 spd = (stat >> 5) & 0x3;
2437 stat &= 0x1f;
2438 switch(stat){
2439 case FWOHCIEV_ACKPEND:
2440#if 0
2441 printf("fwohci_arcv: ack pending..\n");
2442#endif
2443 /* fall through */
2444 case FWOHCIEV_ACKCOMPL:
2445 if( poff != 0 )
2446 bcopy(buf+poff, buf, plen - 4);
2447 fw_rcv(&sc->fc, buf, plen - sizeof(struct fwohci_trailer), 0, 0, spd);
2448 break;
2449 case FWOHCIEV_BUSRST:
2450 free(buf, M_DEVBUF);
2451 if (sc->fc.status != FWBUSRESET)
2452 printf("got BUSRST packet!?\n");
2453 break;
2454 default:
2455 device_printf(sc->fc.dev, "Async DMA Receive error err = %02x %s\n", stat, fwohcicode[stat]);
2456#if 0 /* XXX */
2457 goto out;
2458#endif
2459 break;
2460 }
2461 }
2462 pcnt ++;
2463 };
2464out:
2465 if (resCount == 0) {
2466 /* done on this buffer */
2467 fwohci_add_rx_buf(db_tr, dbch->xferq.psize,
2468 dbch->xferq.flag, 0, NULL);
2469 dbch->bottom->db[0].db.desc.depend |= z;
2470 dbch->bottom = db_tr;
2471 db_tr = STAILQ_NEXT(db_tr, link);
2472 dbch->top = db_tr;
2473 dbch->buf_offset = 0;
2474 } else {
2475 dbch->buf_offset = dbch->xferq.psize - resCount;
2476 break;
2477 }
2478 /* XXX make sure DMA is not dead */
2479 }
2480#if 0
2481 if (pcnt < 1)
2482 printf("fwohci_arcv: no packets\n");
2483#endif
2484 splx(s);
2485}
1730 if (enable) {
1731 sc->intmask |= OHCI_INT_EN;
1732 OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_EN);
1733 } else {
1734 sc->intmask &= ~OHCI_INT_EN;
1735 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN);
1736 }
1737}
1738
1739static void
1740fwohci_tbuf_update(struct fwohci_softc *sc, int dmach)
1741{
1742 int stat;
1743 struct firewire_comm *fc = &sc->fc;
1744 struct fw_pkt *fp;
1745 struct fwohci_dbch *dbch;
1746 struct fwohcidb_tr *db_tr;
1747
1748 dbch = &sc->it[dmach];
1749 if((dbch->xferq.flag & FWXFERQ_DV) && (dbch->xferq.stdma2 != NULL)){
1750 db_tr = (struct fwohcidb_tr *)dbch->xferq.stdma2->start;
1751/*
1752 * Overwrite highest significant 4 bits timestamp information
1753 */
1754 fp = (struct fw_pkt *)db_tr->buf;
1755 fp->mode.ld[2] |= htonl(0x80000000 |
1756 ((fc->cyctimer(fc) + 0x4000) & 0xf000));
1757 }
1758 stat = OREAD(sc, OHCI_ITCTL(dmach)) & 0x1f;
1759 switch(stat){
1760 case FWOHCIEV_ACKCOMPL:
1761 fw_tbuf_update(fc, dmach, 1);
1762 break;
1763 default:
1764 fw_tbuf_update(fc, dmach, 0);
1765 break;
1766 }
1767 fwohci_itxbuf_enable(&sc->fc, dmach);
1768}
1769
1770static void
1771fwohci_rbuf_update(struct fwohci_softc *sc, int dmach)
1772{
1773 int stat;
1774 stat = OREAD(sc, OHCI_IRCTL(dmach)) & 0x1f;
1775 switch(stat){
1776 case FWOHCIEV_ACKCOMPL:
1777 fw_rbuf_update(&sc->fc, dmach, 1);
1778 wakeup(sc->fc.ir[dmach]);
1779 fwohci_irx_enable(&sc->fc, dmach);
1780 break;
1781 default:
1782 break;
1783 }
1784}
1785
1786void
1787dump_dma(struct fwohci_softc *sc, u_int32_t ch)
1788{
1789 u_int32_t off, cntl, stat, cmd, match;
1790
1791 if(ch == 0){
1792 off = OHCI_ATQOFF;
1793 }else if(ch == 1){
1794 off = OHCI_ATSOFF;
1795 }else if(ch == 2){
1796 off = OHCI_ARQOFF;
1797 }else if(ch == 3){
1798 off = OHCI_ARSOFF;
1799 }else if(ch < IRX_CH){
1800 off = OHCI_ITCTL(ch - ITX_CH);
1801 }else{
1802 off = OHCI_IRCTL(ch - IRX_CH);
1803 }
1804 cntl = stat = OREAD(sc, off);
1805 cmd = OREAD(sc, off + 0xc);
1806 match = OREAD(sc, off + 0x10);
1807
1808 device_printf(sc->fc.dev, "dma ch %1x:dma regs 0x%08x 0x%08x 0x%08x 0x%08x \n",
1809 ch,
1810 cntl,
1811 stat,
1812 cmd,
1813 match);
1814 stat &= 0xffff ;
1815 if(stat & 0xff00){
1816 device_printf(sc->fc.dev, "dma %d ch:%s%s%s%s%s%s %s(%x)\n",
1817 ch,
1818 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
1819 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
1820 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
1821 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
1822 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
1823 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
1824 fwohcicode[stat & 0x1f],
1825 stat & 0x1f
1826 );
1827 }else{
1828 device_printf(sc->fc.dev, "dma %d ch: Nostat\n", ch);
1829 }
1830}
1831
1832void
1833dump_db(struct fwohci_softc *sc, u_int32_t ch)
1834{
1835 struct fwohci_dbch *dbch;
1836 struct fwohcidb_tr *cp = NULL, *pp, *np;
1837 volatile struct fwohcidb *curr = NULL, *prev, *next = NULL;
1838 int idb, jdb;
1839 u_int32_t cmd, off;
1840 if(ch == 0){
1841 off = OHCI_ATQOFF;
1842 dbch = &sc->atrq;
1843 }else if(ch == 1){
1844 off = OHCI_ATSOFF;
1845 dbch = &sc->atrs;
1846 }else if(ch == 2){
1847 off = OHCI_ARQOFF;
1848 dbch = &sc->arrq;
1849 }else if(ch == 3){
1850 off = OHCI_ARSOFF;
1851 dbch = &sc->arrs;
1852 }else if(ch < IRX_CH){
1853 off = OHCI_ITCTL(ch - ITX_CH);
1854 dbch = &sc->it[ch - ITX_CH];
1855 }else {
1856 off = OHCI_IRCTL(ch - IRX_CH);
1857 dbch = &sc->ir[ch - IRX_CH];
1858 }
1859 cmd = OREAD(sc, off + 0xc);
1860
1861 if( dbch->ndb == 0 ){
1862 device_printf(sc->fc.dev, "No DB is attached ch=%d\n", ch);
1863 return;
1864 }
1865 pp = dbch->top;
1866 prev = pp->db;
1867 for(idb = 0 ; idb < dbch->ndb ; idb ++ ){
1868 if(pp == NULL){
1869 curr = NULL;
1870 goto outdb;
1871 }
1872 cp = STAILQ_NEXT(pp, link);
1873 if(cp == NULL){
1874 curr = NULL;
1875 goto outdb;
1876 }
1877 np = STAILQ_NEXT(cp, link);
1878 if(cp == NULL) break;
1879 for(jdb = 0 ; jdb < dbch->ndesc ; jdb ++ ){
1880 if((cmd & 0xfffffff0)
1881 == vtophys(&(cp->db[jdb]))){
1882 curr = cp->db;
1883 if(np != NULL){
1884 next = np->db;
1885 }else{
1886 next = NULL;
1887 }
1888 goto outdb;
1889 }
1890 }
1891 pp = STAILQ_NEXT(pp, link);
1892 prev = pp->db;
1893 }
1894outdb:
1895 if( curr != NULL){
1896 printf("Prev DB %d\n", ch);
1897 print_db(prev, ch, dbch->ndesc);
1898 printf("Current DB %d\n", ch);
1899 print_db(curr, ch, dbch->ndesc);
1900 printf("Next DB %d\n", ch);
1901 print_db(next, ch, dbch->ndesc);
1902 }else{
1903 printf("dbdump err ch = %d cmd = 0x%08x\n", ch, cmd);
1904 }
1905 return;
1906}
1907
1908void
1909print_db(volatile struct fwohcidb *db, u_int32_t ch, u_int32_t max)
1910{
1911 fwohcireg_t stat;
1912 int i, key;
1913
1914 if(db == NULL){
1915 printf("No Descriptor is found\n");
1916 return;
1917 }
1918
1919 printf("ch = %d\n%8s %s %s %s %s %4s %8s %8s %4s:%4s\n",
1920 ch,
1921 "Current",
1922 "OP ",
1923 "KEY",
1924 "INT",
1925 "BR ",
1926 "len",
1927 "Addr",
1928 "Depend",
1929 "Stat",
1930 "Cnt");
1931 for( i = 0 ; i <= max ; i ++){
1932 key = db[i].db.desc.cmd & OHCI_KEY_MASK;
1933 printf("%08tx %s %s %s %s %5d %08x %08x %04x:%04x",
1934 vtophys(&db[i]),
1935 dbcode[(db[i].db.desc.cmd >> 28) & 0xf],
1936 dbkey[(db[i].db.desc.cmd >> 24) & 0x7],
1937 dbcond[(db[i].db.desc.cmd >> 20) & 0x3],
1938 dbcond[(db[i].db.desc.cmd >> 18) & 0x3],
1939 db[i].db.desc.cmd & 0xffff,
1940 db[i].db.desc.addr,
1941 db[i].db.desc.depend,
1942 db[i].db.desc.status,
1943 db[i].db.desc.count);
1944 stat = db[i].db.desc.status;
1945 if(stat & 0xff00){
1946 printf(" %s%s%s%s%s%s %s(%x)\n",
1947 stat & OHCI_CNTL_DMA_RUN ? "RUN," : "",
1948 stat & OHCI_CNTL_DMA_WAKE ? "WAKE," : "",
1949 stat & OHCI_CNTL_DMA_DEAD ? "DEAD," : "",
1950 stat & OHCI_CNTL_DMA_ACTIVE ? "ACTIVE," : "",
1951 stat & OHCI_CNTL_DMA_BT ? "BRANCH," : "",
1952 stat & OHCI_CNTL_DMA_BAD ? "BADDMA," : "",
1953 fwohcicode[stat & 0x1f],
1954 stat & 0x1f
1955 );
1956 }else{
1957 printf(" Nostat\n");
1958 }
1959 if(key == OHCI_KEY_ST2 ){
1960 printf("0x%08x 0x%08x 0x%08x 0x%08x\n",
1961 db[i+1].db.immed[0],
1962 db[i+1].db.immed[1],
1963 db[i+1].db.immed[2],
1964 db[i+1].db.immed[3]);
1965 }
1966 if(key == OHCI_KEY_DEVICE){
1967 return;
1968 }
1969 if((db[i].db.desc.cmd & OHCI_BRANCH_MASK)
1970 == OHCI_BRANCH_ALWAYS){
1971 return;
1972 }
1973 if((db[i].db.desc.cmd & OHCI_CMD_MASK)
1974 == OHCI_OUTPUT_LAST){
1975 return;
1976 }
1977 if((db[i].db.desc.cmd & OHCI_CMD_MASK)
1978 == OHCI_INPUT_LAST){
1979 return;
1980 }
1981 if(key == OHCI_KEY_ST2 ){
1982 i++;
1983 }
1984 }
1985 return;
1986}
1987
1988void
1989fwohci_ibr(struct firewire_comm *fc)
1990{
1991 struct fwohci_softc *sc;
1992 u_int32_t fun;
1993
1994 sc = (struct fwohci_softc *)fc;
1995#if 1
1996 fun = fwphy_rddata(sc, FW_PHY_IBR_REG);
1997 fun |= FW_PHY_IBR;
1998 fun = fwphy_wrdata(sc, FW_PHY_IBR_REG, fun);
1999#else
2000 fun = fwphy_rddata(sc, FW_PHY_ISBR_REG);
2001 fun |= FW_PHY_ISBR;
2002 fun = fwphy_wrdata(sc, FW_PHY_ISBR_REG, fun);
2003#endif
2004}
2005
2006void
2007fwohci_txbufdb(struct fwohci_softc *sc, int dmach, struct fw_bulkxfer *bulkxfer)
2008{
2009 struct fwohcidb_tr *db_tr, *fdb_tr;
2010 struct fwohci_dbch *dbch;
2011 struct fw_pkt *fp;
2012 volatile struct fwohci_txpkthdr *ohcifp;
2013 unsigned short chtag;
2014 int idb;
2015
2016 dbch = &sc->it[dmach];
2017 chtag = sc->it[dmach].xferq.flag & 0xff;
2018
2019 db_tr = (struct fwohcidb_tr *)(bulkxfer->start);
2020 fdb_tr = (struct fwohcidb_tr *)(bulkxfer->end);
2021/*
2022device_printf(sc->fc.dev, "DB %08x %08x %08x\n", bulkxfer, vtophys(db_tr->db), vtophys(fdb_tr->db));
2023*/
2024 if(bulkxfer->flag != 0){
2025 return;
2026 }
2027 bulkxfer->flag = 1;
2028 for( idb = 0 ; idb < bulkxfer->npacket ; idb ++){
2029 db_tr->db[0].db.desc.cmd
2030 = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
2031 fp = (struct fw_pkt *)db_tr->buf;
2032 ohcifp = (volatile struct fwohci_txpkthdr *)
2033 db_tr->db[1].db.immed;
2034 ohcifp->mode.ld[0] = ntohl(fp->mode.ld[0]);
2035 ohcifp->mode.stream.len = ntohs(fp->mode.stream.len);
2036 ohcifp->mode.stream.chtag = chtag;
2037 ohcifp->mode.stream.tcode = 0xa;
2038 ohcifp->mode.stream.spd = 4;
2039 ohcifp->mode.ld[2] = ntohl(fp->mode.ld[1]);
2040 ohcifp->mode.ld[3] = ntohl(fp->mode.ld[2]);
2041
2042 db_tr->db[2].db.desc.cmd
2043 = OHCI_OUTPUT_LAST
2044 | OHCI_UPDATE
2045 | OHCI_BRANCH_ALWAYS
2046 | ((ntohs(fp->mode.stream.len) ) & 0xffff);
2047 db_tr->db[2].db.desc.status = 0;
2048 db_tr->db[2].db.desc.count = 0;
2049 if(dbch->xferq.flag & FWXFERQ_DV){
2050 db_tr->db[0].db.desc.depend
2051 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2052 db_tr->db[dbch->ndesc - 1].db.desc.depend
2053 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2054 }else{
2055 db_tr->db[0].db.desc.depend
2056 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2057 db_tr->db[dbch->ndesc - 1].db.desc.depend
2058 = vtophys(STAILQ_NEXT(db_tr, link)->db) | dbch->ndesc;
2059 }
2060 bulkxfer->end = (caddr_t)db_tr;
2061 db_tr = STAILQ_NEXT(db_tr, link);
2062 }
2063 db_tr = (struct fwohcidb_tr *)bulkxfer->end;
2064 db_tr->db[0].db.desc.depend &= ~0xf;
2065 db_tr->db[dbch->ndesc - 1].db.desc.depend &= ~0xf;
2066/**/
2067 db_tr->db[dbch->ndesc - 1].db.desc.cmd &= ~OHCI_BRANCH_ALWAYS;
2068 db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_BRANCH_NEVER;
2069/**/
2070 db_tr->db[dbch->ndesc - 1].db.desc.cmd |= OHCI_INTERRUPT_ALWAYS;
2071
2072 db_tr = (struct fwohcidb_tr *)bulkxfer->start;
2073 fdb_tr = (struct fwohcidb_tr *)bulkxfer->end;
2074/*
2075device_printf(sc->fc.dev, "DB %08x %3d %08x %08x\n", bulkxfer, bulkxfer->npacket, vtophys(db_tr->db), vtophys(fdb_tr->db));
2076*/
2077 return;
2078}
2079
2080static int
2081fwohci_add_tx_buf(struct fwohcidb_tr *db_tr, unsigned short size,
2082 int mode, void *buf)
2083{
2084 volatile struct fwohcidb *db = db_tr->db;
2085 int err = 0;
2086 if(buf == 0){
2087 err = EINVAL;
2088 return err;
2089 }
2090 db_tr->buf = buf;
2091 db_tr->dbcnt = 3;
2092 db_tr->dummy = NULL;
2093
2094 db[0].db.desc.cmd = OHCI_OUTPUT_MORE | OHCI_KEY_ST2 | 8;
2095
2096 db[2].db.desc.depend = 0;
2097 db[2].db.desc.addr = vtophys(buf) + sizeof(u_int32_t);
2098 db[2].db.desc.cmd = OHCI_OUTPUT_MORE;
2099
2100 db[0].db.desc.status = 0;
2101 db[0].db.desc.count = 0;
2102
2103 db[2].db.desc.status = 0;
2104 db[2].db.desc.count = 0;
2105 if( mode & FWXFERQ_STREAM ){
2106 db[2].db.desc.cmd |= OHCI_OUTPUT_LAST;
2107 if(mode & FWXFERQ_PACKET ){
2108 db[2].db.desc.cmd
2109 |= OHCI_INTERRUPT_ALWAYS;
2110 }
2111 }
2112 db[2].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
2113 return 1;
2114}
2115
2116int
2117fwohci_add_rx_buf(struct fwohcidb_tr *db_tr, unsigned short size, int mode,
2118 void *buf, void *dummy)
2119{
2120 volatile struct fwohcidb *db = db_tr->db;
2121 int i;
2122 void *dbuf[2];
2123 int dsiz[2];
2124
2125 if(buf == 0){
2126 buf = malloc(size, M_DEVBUF, M_NOWAIT);
2127 if(buf == NULL) return 0;
2128 db_tr->buf = buf;
2129 db_tr->dbcnt = 1;
2130 db_tr->dummy = NULL;
2131 dsiz[0] = size;
2132 dbuf[0] = buf;
2133 }else if(dummy == NULL){
2134 db_tr->buf = buf;
2135 db_tr->dbcnt = 1;
2136 db_tr->dummy = NULL;
2137 dsiz[0] = size;
2138 dbuf[0] = buf;
2139 }else{
2140 db_tr->buf = buf;
2141 db_tr->dbcnt = 2;
2142 db_tr->dummy = dummy;
2143 dsiz[0] = sizeof(u_int32_t);
2144 dsiz[1] = size;
2145 dbuf[0] = dummy;
2146 dbuf[1] = buf;
2147 }
2148 for(i = 0 ; i < db_tr->dbcnt ; i++){
2149 db[i].db.desc.addr = vtophys(dbuf[i]) ;
2150 db[i].db.desc.cmd = OHCI_INPUT_MORE | dsiz[i];
2151 if( mode & FWXFERQ_STREAM ){
2152 db[i].db.desc.cmd |= OHCI_UPDATE;
2153 }
2154 db[i].db.desc.status = 0;
2155 db[i].db.desc.count = dsiz[i];
2156 }
2157 if( mode & FWXFERQ_STREAM ){
2158 db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_INPUT_LAST;
2159 if(mode & FWXFERQ_PACKET ){
2160 db[db_tr->dbcnt - 1].db.desc.cmd
2161 |= OHCI_INTERRUPT_ALWAYS;
2162 }
2163 }
2164 db[db_tr->dbcnt - 1].db.desc.cmd |= OHCI_BRANCH_ALWAYS;
2165 return 1;
2166}
2167
2168static void
2169fwohci_ircv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2170{
2171 struct fwohcidb_tr *db_tr = dbch->top, *odb_tr;
2172 struct firewire_comm *fc = (struct firewire_comm *)sc;
2173 int z = 1;
2174 struct fw_pkt *fp;
2175 u_int8_t *ld;
2176 u_int32_t off = NULL;
2177 u_int32_t stat;
2178 u_int32_t *qld;
2179 u_int32_t reg;
2180 u_int spd;
2181 u_int dmach;
2182 int len, i, plen;
2183 caddr_t buf;
2184
2185 for(dmach = 0 ; dmach < sc->fc.nisodma ; dmach++){
2186 if( &sc->ir[dmach] == dbch){
2187 off = OHCI_IROFF(dmach);
2188 break;
2189 }
2190 }
2191 if(off == NULL){
2192 return;
2193 }
2194 if(!(dbch->xferq.flag & FWXFERQ_RUNNING)){
2195 fwohci_irx_disable(&sc->fc, dmach);
2196 return;
2197 }
2198
2199 odb_tr = NULL;
2200 db_tr = dbch->top;
2201 i = 0;
2202 while ((reg = db_tr->db[0].db.desc.status) & 0x1f) {
2203 if (count >= 0 && count-- == 0)
2204 break;
2205 ld = (u_int8_t *)db_tr->buf;
2206 if (dbch->xferq.flag & FWXFERQ_PACKET) {
2207 /* skip timeStamp */
2208 ld += sizeof(struct fwohci_trailer);
2209 }
2210 qld = (u_int32_t *)ld;
2211 len = dbch->xferq.psize - (db_tr->db[0].db.desc.count);
2212/*
2213{
2214device_printf(sc->fc.dev, "%04x %2x 0x%08x 0x%08x 0x%08x 0x%08x\n", len,
2215 db_tr->db[0].db.desc.status & 0x1f, qld[0],qld[1],qld[2],qld[3]);
2216}
2217*/
2218 fp=(struct fw_pkt *)ld;
2219 qld[0] = htonl(qld[0]);
2220 plen = sizeof(struct fw_isohdr)
2221 + ntohs(fp->mode.stream.len) + sizeof(u_int32_t);
2222 ld += plen;
2223 len -= plen;
2224 buf = db_tr->buf;
2225 db_tr->buf = NULL;
2226 stat = reg & 0x1f;
2227 spd = reg & 0x3;
2228 switch(stat){
2229 case FWOHCIEV_ACKCOMPL:
2230 case FWOHCIEV_ACKPEND:
2231 fw_rcv(&sc->fc, buf, plen - sizeof(u_int32_t), dmach, sizeof(u_int32_t), spd);
2232 break;
2233 default:
2234 free(buf, M_DEVBUF);
2235 device_printf(sc->fc.dev, "Isochronous receive err %02x\n", stat);
2236 break;
2237 }
2238 i++;
2239 fwohci_add_rx_buf(db_tr, dbch->xferq.psize,
2240 dbch->xferq.flag, 0, NULL);
2241 db_tr->db[0].db.desc.depend &= ~0xf;
2242 if(dbch->pdb_tr != NULL){
2243 dbch->pdb_tr->db[0].db.desc.depend |= z;
2244 } else {
2245 /* XXX should be rewritten in better way */
2246 dbch->bottom->db[0].db.desc.depend |= z;
2247 }
2248 dbch->pdb_tr = db_tr;
2249 db_tr = STAILQ_NEXT(db_tr, link);
2250 }
2251 dbch->top = db_tr;
2252 reg = OREAD(sc, OHCI_DMACTL(off));
2253 if (reg & OHCI_CNTL_DMA_ACTIVE)
2254 return;
2255 device_printf(sc->fc.dev, "IR DMA %d stopped at %x status=%x (%d)\n",
2256 dmach, OREAD(sc, OHCI_DMACMD(off)), reg, i);
2257 dbch->top = db_tr;
2258 fwohci_irx_enable(fc, dmach);
2259}
2260
2261#define PLEN(x) (((ntohs(x))+0x3) & ~0x3)
2262static int
2263fwohci_get_plen(struct fwohci_softc *sc, struct fw_pkt *fp, int hlen)
2264{
2265 int i;
2266
2267 for( i = 4; i < hlen ; i+=4){
2268 fp->mode.ld[i/4] = htonl(fp->mode.ld[i/4]);
2269 }
2270
2271 switch(fp->mode.common.tcode){
2272 case FWTCODE_RREQQ:
2273 return sizeof(fp->mode.rreqq) + sizeof(u_int32_t);
2274 case FWTCODE_WRES:
2275 return sizeof(fp->mode.wres) + sizeof(u_int32_t);
2276 case FWTCODE_WREQQ:
2277 return sizeof(fp->mode.wreqq) + sizeof(u_int32_t);
2278 case FWTCODE_RREQB:
2279 return sizeof(fp->mode.rreqb) + sizeof(u_int32_t);
2280 case FWTCODE_RRESQ:
2281 return sizeof(fp->mode.rresq) + sizeof(u_int32_t);
2282 case FWTCODE_WREQB:
2283 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.wreqb.len)
2284 + sizeof(u_int32_t);
2285 case FWTCODE_LREQ:
2286 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lreq.len)
2287 + sizeof(u_int32_t);
2288 case FWTCODE_RRESB:
2289 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.rresb.len)
2290 + sizeof(u_int32_t);
2291 case FWTCODE_LRES:
2292 return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lres.len)
2293 + sizeof(u_int32_t);
2294 case FWOHCITCODE_PHY:
2295 return 16;
2296 }
2297 device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode);
2298 return 0;
2299}
2300
2301static void
2302fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
2303{
2304 struct fwohcidb_tr *db_tr;
2305 int z = 1;
2306 struct fw_pkt *fp;
2307 u_int8_t *ld;
2308 u_int32_t stat, off;
2309 u_int spd;
2310 int len, plen, hlen, pcnt, poff = 0, rlen;
2311 int s;
2312 caddr_t buf;
2313 int resCount;
2314
2315 if(&sc->arrq == dbch){
2316 off = OHCI_ARQOFF;
2317 }else if(&sc->arrs == dbch){
2318 off = OHCI_ARSOFF;
2319 }else{
2320 return;
2321 }
2322
2323 s = splfw();
2324 db_tr = dbch->top;
2325 pcnt = 0;
2326 /* XXX we cannot handle a packet which lies in more than two buf */
2327 while (db_tr->db[0].db.desc.status & OHCI_CNTL_DMA_ACTIVE) {
2328 ld = (u_int8_t *)db_tr->buf + dbch->buf_offset;
2329 resCount = db_tr->db[0].db.desc.count;
2330 len = dbch->xferq.psize - resCount
2331 - dbch->buf_offset;
2332 while (len > 0 ) {
2333 if (count >= 0 && count-- == 0)
2334 goto out;
2335 if(dbch->frag.buf != NULL){
2336 buf = dbch->frag.buf;
2337 if (dbch->frag.plen < 0) {
2338 /* incomplete header */
2339 int hlen;
2340
2341 hlen = - dbch->frag.plen;
2342 rlen = hlen - dbch->frag.len;
2343 bcopy(ld, dbch->frag.buf + dbch->frag.len, rlen);
2344 ld += rlen;
2345 len -= rlen;
2346 dbch->frag.len += rlen;
2347#if 0
2348 printf("(1)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len);
2349#endif
2350 fp=(struct fw_pkt *)dbch->frag.buf;
2351 dbch->frag.plen
2352 = fwohci_get_plen(sc, fp, hlen);
2353 if (dbch->frag.plen == 0)
2354 goto out;
2355 }
2356 rlen = dbch->frag.plen - dbch->frag.len;
2357#if 0
2358 printf("(2)frag.plen=%d frag.len=%d rlen=%d len=%d\n", dbch->frag.plen, dbch->frag.len, rlen, len);
2359#endif
2360 bcopy(ld, dbch->frag.buf + dbch->frag.len,
2361 rlen);
2362 ld += rlen;
2363 len -= rlen;
2364 plen = dbch->frag.plen;
2365 dbch->frag.buf = NULL;
2366 dbch->frag.plen = 0;
2367 dbch->frag.len = 0;
2368 poff = 0;
2369 }else{
2370 fp=(struct fw_pkt *)ld;
2371 fp->mode.ld[0] = htonl(fp->mode.ld[0]);
2372 switch(fp->mode.common.tcode){
2373 case FWTCODE_RREQQ:
2374 case FWTCODE_WRES:
2375 case FWTCODE_WREQQ:
2376 case FWTCODE_RRESQ:
2377 case FWOHCITCODE_PHY:
2378 hlen = 12;
2379 break;
2380 case FWTCODE_RREQB:
2381 case FWTCODE_WREQB:
2382 case FWTCODE_LREQ:
2383 case FWTCODE_RRESB:
2384 case FWTCODE_LRES:
2385 hlen = 16;
2386 break;
2387 default:
2388 device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode);
2389 goto out;
2390 }
2391 if (len >= hlen) {
2392 plen = fwohci_get_plen(sc, fp, hlen);
2393 if (plen == 0)
2394 goto out;
2395 plen = (plen + 3) & ~3;
2396 len -= plen;
2397 } else {
2398 plen = -hlen;
2399 len -= hlen;
2400 }
2401 if(resCount > 0 || len > 0){
2402 buf = malloc( dbch->xferq.psize,
2403 M_DEVBUF, M_NOWAIT);
2404 if(buf == NULL){
2405 printf("cannot malloc!\n");
2406 free(db_tr->buf, M_DEVBUF);
2407 goto out;
2408 }
2409 bcopy(ld, buf, plen);
2410 poff = 0;
2411 dbch->frag.buf = NULL;
2412 dbch->frag.plen = 0;
2413 dbch->frag.len = 0;
2414 }else if(len < 0){
2415 dbch->frag.buf = db_tr->buf;
2416 if (plen < 0) {
2417#if 0
2418 printf("plen < 0:"
2419 "hlen: %d len: %d\n",
2420 hlen, len);
2421#endif
2422 dbch->frag.len = hlen + len;
2423 dbch->frag.plen = -hlen;
2424 } else {
2425 dbch->frag.len = plen + len;
2426 dbch->frag.plen = plen;
2427 }
2428 bcopy(ld, db_tr->buf, dbch->frag.len);
2429 buf = NULL;
2430 }else{
2431 buf = db_tr->buf;
2432 poff = ld - (u_int8_t *)buf;
2433 dbch->frag.buf = NULL;
2434 dbch->frag.plen = 0;
2435 dbch->frag.len = 0;
2436 }
2437 ld += plen;
2438 }
2439 if( buf != NULL){
2440/* DMA result-code will be written at the tail of packet */
2441 stat = ((struct fwohci_trailer *)(ld - sizeof(struct fwohci_trailer)))->stat;
2442 spd = (stat >> 5) & 0x3;
2443 stat &= 0x1f;
2444 switch(stat){
2445 case FWOHCIEV_ACKPEND:
2446#if 0
2447 printf("fwohci_arcv: ack pending..\n");
2448#endif
2449 /* fall through */
2450 case FWOHCIEV_ACKCOMPL:
2451 if( poff != 0 )
2452 bcopy(buf+poff, buf, plen - 4);
2453 fw_rcv(&sc->fc, buf, plen - sizeof(struct fwohci_trailer), 0, 0, spd);
2454 break;
2455 case FWOHCIEV_BUSRST:
2456 free(buf, M_DEVBUF);
2457 if (sc->fc.status != FWBUSRESET)
2458 printf("got BUSRST packet!?\n");
2459 break;
2460 default:
2461 device_printf(sc->fc.dev, "Async DMA Receive error err = %02x %s\n", stat, fwohcicode[stat]);
2462#if 0 /* XXX */
2463 goto out;
2464#endif
2465 break;
2466 }
2467 }
2468 pcnt ++;
2469 };
2470out:
2471 if (resCount == 0) {
2472 /* done on this buffer */
2473 fwohci_add_rx_buf(db_tr, dbch->xferq.psize,
2474 dbch->xferq.flag, 0, NULL);
2475 dbch->bottom->db[0].db.desc.depend |= z;
2476 dbch->bottom = db_tr;
2477 db_tr = STAILQ_NEXT(db_tr, link);
2478 dbch->top = db_tr;
2479 dbch->buf_offset = 0;
2480 } else {
2481 dbch->buf_offset = dbch->xferq.psize - resCount;
2482 break;
2483 }
2484 /* XXX make sure DMA is not dead */
2485 }
2486#if 0
2487 if (pcnt < 1)
2488 printf("fwohci_arcv: no packets\n");
2489#endif
2490 splx(s);
2491}