2 * Copyright (c) 1999 Michael Smith
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/sys/dev/mlx/mlx_pci.c,v 1.4.2.5 2001/06/25 04:37:51 msmith Exp $
27 * $DragonFly: src/sys/dev/raid/mlx/mlx_pci.c,v 1.4 2006/10/25 20:56:01 dillon Exp $
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
35 #include <sys/devicestat.h>
39 #include <bus/pci/pcireg.h>
40 #include <bus/pci/pcivar.h>
42 #include "mlx_compat.h"
47 static int mlx_pci_probe(device_t dev
);
48 static int mlx_pci_attach(device_t dev
);
50 static device_method_t mlx_methods
[] = {
51 /* Device interface */
52 DEVMETHOD(device_probe
, mlx_pci_probe
),
53 DEVMETHOD(device_attach
, mlx_pci_attach
),
54 DEVMETHOD(device_detach
, mlx_detach
),
55 DEVMETHOD(device_shutdown
, mlx_shutdown
),
56 DEVMETHOD(device_suspend
, mlx_suspend
),
57 DEVMETHOD(device_resume
, mlx_resume
),
59 DEVMETHOD(bus_print_child
, bus_generic_print_child
),
60 DEVMETHOD(bus_driver_added
, bus_generic_driver_added
),
64 static driver_t mlx_pci_driver
= {
67 sizeof(struct mlx_softc
)
70 DRIVER_MODULE(mlx
, pci
, mlx_pci_driver
, mlx_devclass
, 0, 0);
80 } mlx_identifiers
[] = {
81 {0x1069, 0x0001, 0x0000, 0x0000, MLX_IFTYPE_2
, "Mylex version 2 RAID interface"},
82 {0x1069, 0x0002, 0x0000, 0x0000, MLX_IFTYPE_3
, "Mylex version 3 RAID interface"},
83 {0x1069, 0x0010, 0x0000, 0x0000, MLX_IFTYPE_4
, "Mylex version 4 RAID interface"},
84 {0x1011, 0x1065, 0x1069, 0x0020, MLX_IFTYPE_5
, "Mylex version 5 RAID interface"},
89 mlx_pci_probe(device_t dev
)
95 for (m
= mlx_identifiers
; m
->vendor
!= 0; m
++) {
96 if ((m
->vendor
== pci_get_vendor(dev
)) &&
97 (m
->device
== pci_get_device(dev
)) &&
98 ((m
->subvendor
== 0) || ((m
->subvendor
== pci_get_subvendor(dev
)) &&
99 (m
->subdevice
== pci_get_subdevice(dev
))))) {
101 device_set_desc(dev
, m
->desc
);
102 return(-10); /* allow room to be overridden */
109 mlx_pci_attach(device_t dev
)
111 struct mlx_softc
*sc
;
118 * Make sure we are going to be able to talk to this board.
120 command
= pci_read_config(dev
, PCIR_COMMAND
, 2);
121 if ((command
& PCIM_CMD_MEMEN
) == 0) {
122 device_printf(dev
, "memory window not available\n");
125 /* force the busmaster enable bit on */
126 command
|= PCIM_CMD_BUSMASTEREN
;
127 pci_write_config(dev
, PCIR_COMMAND
, command
, 2);
132 sc
= device_get_softc(dev
);
133 bzero(sc
, sizeof(*sc
));
137 * Work out what sort of adapter this is (we need to know this in order
138 * to map the appropriate interface resources).
141 for (i
= 0; mlx_identifiers
[i
].vendor
!= 0; i
++) {
142 if ((mlx_identifiers
[i
].vendor
== pci_get_vendor(dev
)) &&
143 (mlx_identifiers
[i
].device
== pci_get_device(dev
))) {
144 sc
->mlx_iftype
= mlx_identifiers
[i
].iftype
;
148 if (sc
->mlx_iftype
== 0) /* shouldn't happen */
152 * Allocate the PCI register window.
155 /* type 2/3 adapters have an I/O region we don't prefer at base 0 */
156 switch(sc
->mlx_iftype
) {
159 sc
->mlx_mem_type
= SYS_RES_MEMORY
;
160 sc
->mlx_mem_rid
= MLX_CFG_BASE1
;
161 sc
->mlx_mem
= bus_alloc_resource(dev
, sc
->mlx_mem_type
, &sc
->mlx_mem_rid
, 0, ~0, 1, RF_ACTIVE
);
162 if (sc
->mlx_mem
== NULL
) {
163 sc
->mlx_mem_type
= SYS_RES_IOPORT
;
164 sc
->mlx_mem_rid
= MLX_CFG_BASE0
;
165 sc
->mlx_mem
= bus_alloc_resource(dev
, sc
->mlx_mem_type
, &sc
->mlx_mem_rid
, 0, ~0, 1, RF_ACTIVE
);
170 sc
->mlx_mem_type
= SYS_RES_MEMORY
;
171 sc
->mlx_mem_rid
= MLX_CFG_BASE0
;
172 sc
->mlx_mem
= bus_alloc_resource(dev
, sc
->mlx_mem_type
, &sc
->mlx_mem_rid
, 0, ~0, 1, RF_ACTIVE
);
175 if (sc
->mlx_mem
== NULL
) {
176 device_printf(sc
->mlx_dev
, "couldn't allocate mailbox window\n");
180 sc
->mlx_btag
= rman_get_bustag(sc
->mlx_mem
);
181 sc
->mlx_bhandle
= rman_get_bushandle(sc
->mlx_mem
);
184 * Allocate the parent bus DMA tag appropriate for PCI.
186 error
= bus_dma_tag_create(NULL
, /* parent */
187 1, 0, /* alignment, boundary */
188 BUS_SPACE_MAXADDR_32BIT
, /* lowaddr */
189 BUS_SPACE_MAXADDR
, /* highaddr */
190 NULL
, NULL
, /* filter, filterarg */
191 MAXBSIZE
, MLX_NSEG
, /* maxsize, nsegments */
192 BUS_SPACE_MAXSIZE_32BIT
, /* maxsegsize */
193 BUS_DMA_ALLOCNOW
, /* flags */
194 &sc
->mlx_parent_dmat
);
196 device_printf(dev
, "can't allocate parent DMA tag\n");
202 * Do bus-independant initialisation.
204 error
= mlx_attach(sc
);
211 * Start the controller.