2 * Copyright (c) 1996 - 2001 John Hay.
3 * Copyright (c) 1996 SDL Communications, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the names of any co-contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * $FreeBSD: src/sys/dev/sr/if_sr_pci.c,v 1.15.2.1 2002/06/17 15:10:58 jhay Exp $
31 * $DragonFly: src/sys/dev/netif/sr/if_sr_pci.c,v 1.7 2008/01/05 14:02:37 swildner Exp $
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
42 #include <bus/pci/pcivar.h>
43 #include <machine/md_var.h>
45 #include "../ic_layer/hd64570.h"
46 #include "if_srregs.h"
52 static int sr_pci_probe(device_t
);
53 static int sr_pci_attach(device_t
);
55 static device_method_t sr_pci_methods
[] = {
56 /* Device interface */
57 DEVMETHOD(device_probe
, sr_pci_probe
),
58 DEVMETHOD(device_attach
, sr_pci_attach
),
59 DEVMETHOD(device_detach
, sr_detach
),
63 static driver_t sr_pci_driver
= {
66 sizeof(struct sr_hardc
),
69 DRIVER_MODULE(if_sr
, pci
, sr_pci_driver
, sr_devclass
, 0, 0);
71 static u_int
src_get8_mem(u_int base
, u_int off
);
72 static u_int
src_get16_mem(u_int base
, u_int off
);
73 static void src_put8_mem(u_int base
, u_int off
, u_int val
);
74 static void src_put16_mem(u_int base
, u_int off
, u_int val
);
77 sr_pci_probe(device_t device
)
79 u_int32_t type
= pci_get_devid(device
);
83 device_set_desc(device
, "RISCom/N2pci");
89 * XXX This can probably be removed sometime.
91 device_set_desc(device
, "RISCom/N2pci (old id)");
101 sr_pci_attach(device_t device
)
107 hc
= (struct sr_hardc
*)device_get_softc(device
);
109 if (sr_allocate_plx_memory(device
, 0x10, 1))
112 if (sr_allocate_memory(device
, 0x18, 1))
115 if (sr_allocate_irq(device
, 0, 1))
118 hc
->plx_base
= rman_get_virtual(hc
->res_plx_memory
);
119 hc
->sca_base
= (vm_offset_t
)rman_get_virtual(hc
->res_memory
);
121 hc
->cunit
= device_get_unit(device
);
125 * Configure the PLX. This is magic. I'm doing it just like I'm told
129 * 0x00 - Map Range - Mem-mapped to locate anywhere
130 * 0x04 - Re-Map - PCI address decode enable
131 * 0x18 - Bus Region - 32-bit bus, ready enable
132 * 0x1c - Master Range - include all 16 MB
133 * 0x20 - Master RAM - Map SCA Base at 0
134 * 0x28 - Master Remap - direct master memory enable
135 * 0x68 - Interrupt - Enable interrupt (0 to disable)
137 * Note: This is "cargo cult" stuff. - jrc
139 *((u_int
*)(hc
->plx_base
+ 0x00)) = 0xfffff000;
140 *((u_int
*)(hc
->plx_base
+ 0x04)) = 1;
141 *((u_int
*)(hc
->plx_base
+ 0x18)) = 0x40030043;
142 *((u_int
*)(hc
->plx_base
+ 0x1c)) = 0xff000000;
143 *((u_int
*)(hc
->plx_base
+ 0x20)) = 0;
144 *((u_int
*)(hc
->plx_base
+ 0x28)) = 0xe9;
145 *((u_int
*)(hc
->plx_base
+ 0x68)) = 0x10900;
148 * Get info from card.
150 * Only look for the second port if the first exists. Too many things
151 * will break if we have only a second port.
153 fecrp
= (u_int
*)(hc
->sca_base
+ SR_FECR
);
157 if (((fecr
& SR_FECR_ID0
) >> SR_FE_ID0_SHFT
) != SR_FE_ID_NONE
) {
159 if (((fecr
& SR_FECR_ID1
) >> SR_FE_ID1_SHFT
) != SR_FE_ID_NONE
)
165 hc
->numports
= numports
;
166 hc
->cardtype
= SR_CRD_N2PCI
;
168 hc
->src_put8
= src_put8_mem
;
169 hc
->src_put16
= src_put16_mem
;
170 hc
->src_get8
= src_get8_mem
;
171 hc
->src_get16
= src_get16_mem
;
174 * Malloc area for tx and rx buffers. For now allocate SRC_WIN_SIZ
175 * (16k) for each buffer.
177 * Allocate the block below 16M because the N2pci card can only access
178 * 16M memory at a time.
180 * (We could actually allocate a contiguous block above the 16MB limit,
181 * but this would complicate card programming more than we want to
184 hc
->memsize
= 2 * hc
->numports
* SRC_WIN_SIZ
;
185 hc
->mem_start
= contigmalloc(hc
->memsize
,
193 if (hc
->mem_start
== NULL
) {
194 kprintf("src%d: pci: failed to allocate buffer space.\n",
198 hc
->winmsk
= 0xffffffff;
199 hc
->mem_end
= (caddr_t
)((u_int
)hc
->mem_start
+ hc
->memsize
);
200 hc
->mem_pstart
= kvtop(hc
->mem_start
);
202 *fecrp
= SR_FECR_DTR0
207 if (sr_attach(device
))
212 sr_deallocate_resources(device
);
217 * I/O for PCI N2 card(s)
219 #define SRC_PCI_SCA_REG(y) ((y & 2) ? ((y & 0xfd) + 0x100) : y)
222 src_get8_mem(u_int base
, u_int off
)
224 return *((u_char
*)(base
+ SRC_PCI_SCA_REG(off
)));
228 src_get16_mem(u_int base
, u_int off
)
230 return *((u_short
*)(base
+ SRC_PCI_SCA_REG(off
)));
234 src_put8_mem(u_int base
, u_int off
, u_int val
)
236 *((u_char
*)(base
+ SRC_PCI_SCA_REG(off
))) = (u_char
)val
;
240 src_put16_mem(u_int base
, u_int off
, u_int val
)
242 *((u_short
*)(base
+ SRC_PCI_SCA_REG(off
))) = (u_short
)val
;