1 /* $NetBSD: if_iee_gsc.c,v 1.15 2009/05/24 06:53:35 skrll Exp $ */
4 * Copyright (c) 2003 Jochen Kunz.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of Jochen Kunz may not be used to endorse or promote
16 * products derived from this software without specific prior
19 * THIS SOFTWARE IS PROVIDED BY JOCHEN KUNZ
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JOCHEN KUNZ
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * hp700 GSC bus MD frontend for the iee(4) Intel i82596 Ethernet driver.
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: if_iee_gsc.c,v 1.15 2009/05/24 06:53:35 skrll Exp $");
39 /* autoconfig and device stuff */
40 #include <sys/param.h>
41 #include <sys/device.h>
43 #include <machine/iomod.h>
44 #include <machine/autoconf.h>
45 #include <hp700/dev/cpudevs.h>
46 #include <hp700/gsc/gscbusvar.h>
50 /* bus_space / bus_dma etc. */
51 #include <machine/bus.h>
52 #include <machine/intr.h>
54 /* general system data and functions */
55 #include <sys/systm.h>
56 #include <sys/ioctl.h>
57 #include <sys/ioccom.h>
58 #include <sys/types.h>
60 /* tsleep / sleep / wakeup */
63 #include <sys/kernel.h>
67 #include <net/if_dl.h>
68 #include <net/if_media.h>
69 #include <net/if_ether.h>
70 #include <sys/socket.h>
78 #include <dev/ic/i82596reg.h>
79 #include <dev/ic/i82596var.h>
81 #define IEE_GSC_IO_SZ 12
82 #define IEE_GSC_RESET 0
83 #define IEE_GSC_PORT 4
84 #define IEE_GSC_CHANATT 8
85 #define IEE_ISCP_BUSY 0x1
87 /* autoconfig stuff */
88 static int iee_gsc_match(device_t
, cfdata_t
, void *);
89 static void iee_gsc_attach(device_t
, device_t
, void *);
90 static int iee_gsc_detach(device_t
, int);
92 struct iee_gsc_softc
{
93 struct iee_softc iee_sc
;
94 bus_space_tag_t sc_iot
;
95 bus_space_handle_t sc_ioh
;
101 sizeof(struct iee_gsc_softc
),
108 int iee_gsc_cmd(struct iee_softc
*, uint32_t);
109 int iee_gsc_reset(struct iee_softc
*);
112 iee_gsc_cmd(struct iee_softc
*sc
, uint32_t cmd
)
114 struct iee_gsc_softc
*sc_gsc
= (struct iee_gsc_softc
*)sc
;
118 SC_SCB(sc
)->scb_cmd
= cmd
;
119 IEE_SCBSYNC(sc
, BUS_DMASYNC_PREREAD
|BUS_DMASYNC_PREWRITE
);
120 /* Issue a Channel Attention to force the chip to read the cmd. */
121 bus_space_write_4(sc_gsc
->sc_iot
, sc_gsc
->sc_ioh
, IEE_GSC_CHANATT
, 0);
122 /* Wait for the cmd to finish */
123 for (n
= 0 ; n
< 100000; n
++) {
125 IEE_SCBSYNC(sc
, BUS_DMASYNC_POSTREAD
|BUS_DMASYNC_POSTWRITE
);
126 ack
= SC_SCB(sc
)->scb_cmd
;
127 IEE_SCBSYNC(sc
, BUS_DMASYNC_PREREAD
);
133 printf("%s: iee_gsc_cmd: timeout n=%d\n", device_xname(sc
->sc_dev
), n
);
138 iee_gsc_reset(struct iee_softc
*sc
)
140 struct iee_gsc_softc
*sc_gsc
= (struct iee_gsc_softc
*)sc
;
145 /* Make sure the busy byte is set and the cache is flushed. */
146 SC_ISCP(sc
)->iscp_busy
= IEE_ISCP_BUSY
;
147 IEE_ISCPSYNC(sc
, BUS_DMASYNC_PREREAD
|BUS_DMASYNC_PREWRITE
);
148 /* Setup the PORT Command with pointer to SCP. */
149 cmd
= IEE_PORT_SCP
| IEE_PHYS_SHMEM(sc
->sc_scp_off
);
150 /* Write a word to IEE_GSC_RESET to initiate a Hardware reset. */
151 bus_space_write_4(sc_gsc
->sc_iot
, sc_gsc
->sc_ioh
, IEE_GSC_RESET
, 0);
153 /* Write it to the chip, it wants this in two 16 bit parts. */
154 if (sc
->sc_type
== I82596_CA
) {
155 bus_space_write_4(sc_gsc
->sc_iot
, sc_gsc
->sc_ioh
, IEE_GSC_PORT
,
158 bus_space_write_4(sc_gsc
->sc_iot
, sc_gsc
->sc_ioh
, IEE_GSC_PORT
,
161 bus_space_write_4(sc_gsc
->sc_iot
, sc_gsc
->sc_ioh
, IEE_GSC_PORT
,
164 bus_space_write_4(sc_gsc
->sc_iot
, sc_gsc
->sc_ioh
, IEE_GSC_PORT
,
168 /* Issue a Channel Attention to read SCP */
169 bus_space_write_4(sc_gsc
->sc_iot
, sc_gsc
->sc_ioh
, IEE_GSC_CHANATT
, 0);
170 /* Wait for the chip to initialize and read SCP and ISCP. */
171 for (n
= 0 ; n
< 1000; n
++) {
172 IEE_ISCPSYNC(sc
, BUS_DMASYNC_POSTREAD
|BUS_DMASYNC_POSTWRITE
);
173 ack
= SC_ISCP(sc
)->iscp_busy
;
174 IEE_ISCPSYNC(sc
, BUS_DMASYNC_PREREAD
);
175 if (ack
!= IEE_ISCP_BUSY
)
180 /* ACK interrupts we may have caused */
181 (sc
->sc_iee_cmd
)(sc
, IEE_SCB_ACK
);
184 printf("%s: iee_gsc_reset timeout busy=0x%x\n",
185 device_xname(sc
->sc_dev
), SC_ISCP(sc
)->iscp_busy
);
190 iee_gsc_match(device_t parent
, cfdata_t cf
, void *aux
)
192 struct gsc_attach_args
*ga
= aux
;
194 if (ga
->ga_type
.iodc_type
== HPPA_TYPE_FIO
195 && (ga
->ga_type
.iodc_sv_model
== HPPA_FIO_LAN
196 || ga
->ga_type
.iodc_sv_model
== HPPA_FIO_GLAN
))
197 /* beat old ie(4) i82586 driver */
203 iee_gsc_attach(device_t parent
, device_t self
, void *aux
)
205 struct iee_gsc_softc
*sc_gsc
= device_private(self
);
206 struct iee_softc
*sc
= &sc_gsc
->iee_sc
;
207 struct gsc_attach_args
*ga
= aux
;
208 enum hppa_cpu_type cpu_type
;
213 if (ga
->ga_type
.iodc_sv_model
== HPPA_FIO_LAN
)
214 sc
->sc_type
= I82596_DX
; /* ASP(2) based */
216 sc
->sc_type
= I82596_CA
; /* LASI based */
218 * Pre PA7100LC CPUs don't support uncacheable mappings. So make
219 * descriptors align to cache lines. Needed to avoid race conditions
220 * caused by flushing cache lines that overlap multiple descriptors.
222 cpu_type
= hppa_cpu_info
->hci_cputype
;
223 if (cpu_type
== hpcx
|| cpu_type
== hpcxs
|| cpu_type
== hpcxt
)
224 sc
->sc_cl_align
= 32;
228 sc_gsc
->sc_iot
= ga
->ga_iot
;
229 if (bus_space_map(sc_gsc
->sc_iot
, ga
->ga_hpa
, IEE_GSC_IO_SZ
, 0,
231 aprint_error(": iee_gsc_attach: can't map I/O space\n");
235 sc
->sc_dmat
= ga
->ga_dmatag
;
237 /* Setup SYSBUS byte. */
238 if (ga
->ga_type
.iodc_sv_model
== HPPA_FIO_LAN
) {
240 * Some earlier machines have 82596DX Rev A1 chip
241 * which doesn't have IEE_SYSBUS_BE for 32-bit BE pointers.
243 * XXX: How can we detect chip revision at runtime?
244 * Should we check cpu_models instead?
245 * 715/50, 735/99: Rev A1? (per PR port-hp700/35531)
248 sc
->sc_sysbus
= IEE_SYSBUS_INT
|
249 IEE_SYSBUS_TRG
| IEE_SYSBUS_LIEAR
| IEE_SYSBUS_STD
;
250 sc
->sc_flags
= IEE_NEED_SWAP
| IEE_REV_A
;
252 sc
->sc_sysbus
= IEE_SYSBUS_BE
| IEE_SYSBUS_INT
|
253 IEE_SYSBUS_TRG
| IEE_SYSBUS_LIEAR
| IEE_SYSBUS_STD
;
254 sc
->sc_flags
= IEE_NEED_SWAP
;
257 sc_gsc
->sc_ih
= hp700_intr_establish(self
, IPL_NET
,
258 iee_intr
, sc
, ga
->ga_int_reg
, ga
->ga_irq
);
260 sc
->sc_iee_reset
= iee_gsc_reset
;
261 sc
->sc_iee_cmd
= iee_gsc_cmd
;
262 sc
->sc_mediachange
= NULL
;
263 sc
->sc_mediastatus
= NULL
;
265 media
[0] = IFM_ETHER
| IFM_MANUAL
;
266 media
[1] = IFM_ETHER
| IFM_AUTO
;
267 iee_attach(sc
, ga
->ga_ether_address
, media
, 2, IFM_ETHER
| IFM_AUTO
);
271 iee_gsc_detach(device_t self
, int flags
)
273 struct iee_gsc_softc
*sc_gsc
= device_private(self
);
274 struct iee_softc
*sc
= &sc_gsc
->iee_sc
;
276 iee_detach(sc
, flags
);
277 bus_space_unmap(sc_gsc
->sc_iot
, sc_gsc
->sc_ioh
, IEE_GSC_IO_SZ
);
278 /* There is no hp700_intr_disestablish()! */