2 * Copyright (c) 2002 Adaptec Inc.
5 * Written by: David Jeffery
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.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $FreeBSD: src/sys/dev/ips/ips_pci.c,v 1.10 2004/03/19 17:36:47 scottl Exp $
29 * $DragonFly: src/sys/dev/raid/ips/ips_pci.c,v 1.17 2006/12/22 23:26:23 swildner Exp $
32 #include <dev/raid/ips/ips.h>
34 static int ips_pci_free(ips_softc_t
*sc
);
35 static void ips_intrhook(void *arg
);
37 static struct ips_pci_product
{
38 uint16_t vendor
, device
;
40 int (*ips_adapter_reinit
)(struct ips_softc
*, int);
41 void (*ips_adapter_intr
)(void *);
42 void (*ips_issue_cmd
)(ips_command_t
*);
43 void (*ips_poll_cmd
)(ips_command_t
*);
44 } ips_pci_products
[] = {
45 { IPS_VENDOR_ID
, IPS_MORPHEUS_DEVICE_ID
, "IBM ServeRAID Adapter",
46 ips_morpheus_reinit
, ips_morpheus_intr
, ips_issue_morpheus_cmd
,
48 { IPS_VENDOR_ID
, IPS_COPPERHEAD_DEVICE_ID
, "IBM ServeRAID Adapter",
49 ips_copperhead_reinit
, ips_copperhead_intr
, ips_issue_copperhead_cmd
,
50 ips_copperhead_poll
},
51 { IPS_VENDOR_ID_ADAPTEC
, IPS_MARCO_DEVICE_ID
,
52 "Adaptec ServeRAID Adapter", ips_morpheus_reinit
, ips_morpheus_intr
,
53 ips_issue_morpheus_cmd
, ips_morpheus_poll
},
58 ips_pci_probe(device_t dev
)
60 uint16_t vendor
= pci_get_vendor(dev
);
61 uint16_t device
= pci_get_device(dev
);
62 struct ips_pci_product
*pp
;
65 for (pp
= ips_pci_products
; pp
->vendor
; pp
++) {
66 if (vendor
== pp
->vendor
&& device
== pp
->device
) {
67 sc
= (ips_softc_t
*)device_get_softc(dev
);
68 sc
->ips_adapter_reinit
= pp
->ips_adapter_reinit
;
69 sc
->ips_adapter_intr
= pp
->ips_adapter_intr
;
70 sc
->ips_issue_cmd
= pp
->ips_issue_cmd
;
71 sc
->ips_poll_cmd
= pp
->ips_poll_cmd
;
72 device_set_desc(dev
, pp
->desc
);
80 ips_pci_attach(device_t dev
)
86 if (resource_disabled(device_get_name(dev
), device_get_unit(dev
))) {
87 device_printf(dev
, "device is disabled\n");
88 /* but return 0 so the !$)$)*!$*) unit isn't reused */
91 DEVICE_PRINTF(1, dev
, "in attach.\n");
92 sc
= (ips_softc_t
*)device_get_softc(dev
);
94 /* make sure busmastering is on */
95 pci_enable_busmaster(dev
);
96 command
= pci_read_config(dev
, PCIR_COMMAND
, 1);
97 /* seting up io space */
99 if (command
& PCIM_CMD_MEMEN
) {
100 PRINTF(10, "trying MEMIO\n");
101 if (pci_get_device(dev
) == IPS_COPPERHEAD_DEVICE_ID
)
102 sc
->rid
= PCIR_BAR(1);
104 sc
->rid
= PCIR_BAR(0);
105 sc
->iotype
= SYS_RES_MEMORY
;
106 sc
->iores
= bus_alloc_resource_any(dev
, sc
->iotype
,
107 &sc
->rid
, RF_ACTIVE
);
109 if (sc
->iores
== NULL
&& command
& PCIM_CMD_PORTEN
) {
110 PRINTF(10, "trying PORTIO\n");
111 sc
->rid
= PCIR_BAR(0);
112 sc
->iotype
= SYS_RES_IOPORT
;
113 sc
->iores
= bus_alloc_resource_any(dev
, sc
->iotype
,
114 &sc
->rid
, RF_ACTIVE
);
116 if (sc
->iores
== NULL
) {
117 device_printf(dev
, "resource allocation failed\n");
120 sc
->bustag
= rman_get_bustag(sc
->iores
);
121 sc
->bushandle
= rman_get_bushandle(sc
->iores
);
123 * allocate an interrupt. when does the irq become active?
124 * after leaving attach?
127 if ((sc
->irqres
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
,
128 &sc
->irqrid
, RF_SHAREABLE
| RF_ACTIVE
)) == NULL
) {
129 device_printf(dev
, "irq allocation failed\n");
132 error
= bus_setup_intr(dev
, sc
->irqres
, 0,
133 sc
->ips_adapter_intr
, sc
,
134 &sc
->irqcookie
, NULL
);
136 device_printf(dev
, "irq setup failed\n");
139 if (bus_dma_tag_create( /* parent */ NULL
,
142 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT
,
143 /* highaddr */ BUS_SPACE_MAXADDR
,
145 /* filterarg */ NULL
,
146 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT
,
147 /* numsegs */ IPS_MAX_SG_ELEMENTS
,
148 /* maxsegsize*/ BUS_SPACE_MAXSIZE_32BIT
,
150 &sc
->adapter_dmatag
) != 0) {
151 kprintf("IPS can't alloc dma tag\n");
154 sc
->ips_ich
.ich_func
= ips_intrhook
;
155 sc
->ips_ich
.ich_arg
= sc
;
156 sc
->ips_ich
.ich_desc
= "ips";
157 lockinit(&sc
->queue_lock
, "ipslk", 0, 0);
158 bioq_init(&sc
->bio_queue
);
159 if (config_intrhook_establish(&sc
->ips_ich
) != 0) {
160 kprintf("IPS can't establish configuration hook\n");
170 ips_intrhook(void *arg
)
172 struct ips_softc
*sc
= arg
;
174 config_intrhook_disestablish(&sc
->ips_ich
);
175 if (ips_adapter_init(sc
))
182 ips_pci_free(ips_softc_t
*sc
)
185 if (sc
->adapter_dmatag
)
186 bus_dma_tag_destroy(sc
->adapter_dmatag
);
188 bus_teardown_intr(sc
->dev
, sc
->irqres
, sc
->irqcookie
);
190 bus_release_resource(sc
->dev
, SYS_RES_IRQ
, sc
->irqrid
,
193 bus_release_resource(sc
->dev
, sc
->iotype
, sc
->rid
, sc
->iores
);
199 ips_pci_detach(device_t dev
)
203 DEVICE_PRINTF(1, dev
, "detaching ServeRaid\n");
204 sc
= (ips_softc_t
*)device_get_softc(dev
);
205 if (sc
->configured
) {
208 if (ips_adapter_free(sc
))
216 ips_pci_shutdown(device_t dev
)
220 sc
= (ips_softc_t
*)device_get_softc(dev
);
226 static device_method_t ips_driver_methods
[] = {
227 DEVMETHOD(device_probe
, ips_pci_probe
),
228 DEVMETHOD(device_attach
, ips_pci_attach
),
229 DEVMETHOD(device_detach
, ips_pci_detach
),
230 DEVMETHOD(device_shutdown
, ips_pci_shutdown
),
234 static driver_t ips_pci_driver
= {
240 static devclass_t ips_devclass
;
241 DRIVER_MODULE(ips
, pci
, ips_pci_driver
, ips_devclass
, 0, 0);