ips_pci.c revision 117167
1/*-
2 * Copyright (c) 2002 Adaptec Inc.
3 * All rights reserved.
4 *
5 * Written by: David Jeffery
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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 *
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
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/dev/ips/ips_pci.c 117167 2003-07-02 16:09:02Z jhb $
29 */
30
31
32#include <dev/ips/ips.h>
33static int ips_pci_free(ips_softc_t *sc);
34
35static int ips_pci_probe(device_t dev)
36{
37
38        if ((pci_get_vendor(dev) == IPS_VENDOR_ID) &&
39	    (pci_get_device(dev) == IPS_MORPHEUS_DEVICE_ID)) {
40		device_set_desc(dev, "IBM ServeRAID Adapter");
41                return 0;
42        } else if ((pci_get_vendor(dev) == IPS_VENDOR_ID) &&
43	    (pci_get_device(dev) == IPS_COPPERHEAD_DEVICE_ID)) {
44		device_set_desc(dev, "IBM ServeRAID Adapter");
45		return (0);
46        }
47        return(ENXIO);
48}
49
50static int ips_pci_attach(device_t dev)
51{
52        u_int32_t command;
53        ips_softc_t *sc;
54
55
56	if (resource_disabled(device_get_name(dev), device_get_unit(dev))) {
57		device_printf(dev, "device is disabled\n");
58		/* but return 0 so the !$)$)*!$*) unit isn't reused */
59		return (0);
60	}
61        DEVICE_PRINTF(1, dev, "in attach.\n");
62        sc = (ips_softc_t *)device_get_softc(dev);
63        if(!sc){
64                printf("how is sc NULL?!\n");
65                return (ENXIO);
66        }
67        bzero(sc, sizeof(ips_softc_t));
68        sc->dev = dev;
69
70        if(pci_get_device(dev) == IPS_MORPHEUS_DEVICE_ID){
71		sc->ips_adapter_reinit = ips_morpheus_reinit;
72                sc->ips_adapter_intr = ips_morpheus_intr;
73		sc->ips_issue_cmd    = ips_issue_morpheus_cmd;
74        } else if(pci_get_device(dev) == IPS_COPPERHEAD_DEVICE_ID){
75		sc->ips_adapter_reinit = ips_copperhead_reinit;
76                sc->ips_adapter_intr = ips_copperhead_intr;
77		sc->ips_issue_cmd    = ips_issue_copperhead_cmd;
78	} else
79                goto error;
80        /* make sure busmastering is on */
81        command = pci_read_config(dev, PCIR_COMMAND, 1);
82	command |= PCIM_CMD_BUSMASTEREN;
83	pci_write_config(dev, PCIR_COMMAND, command, 1);
84        /* seting up io space */
85        sc->iores = NULL;
86        if(command & PCIM_CMD_MEMEN){
87                PRINTF(10, "trying MEMIO\n");
88		if(pci_get_device(dev) == IPS_MORPHEUS_DEVICE_ID)
89                	sc->rid = PCIR_MAPS;
90		else
91			sc->rid = PCIR_MAPS + 4;
92                sc->iotype = SYS_RES_MEMORY;
93                sc->iores = bus_alloc_resource(dev, sc->iotype, &sc->rid, 0, ~0, 1, RF_ACTIVE);
94        }
95        if(!sc->iores && command & PCIM_CMD_PORTEN){
96                PRINTF(10, "trying PORTIO\n");
97                sc->rid = PCIR_MAPS;
98                sc->iotype = SYS_RES_IOPORT;
99                sc->iores = bus_alloc_resource(dev, sc->iotype, &sc->rid, 0, ~0, 1, RF_ACTIVE);
100        }
101        if(sc->iores == NULL){
102                device_printf(dev, "resource allocation failed\n");
103                return (ENXIO);
104        }
105        sc->bustag = rman_get_bustag(sc->iores);
106        sc->bushandle = rman_get_bushandle(sc->iores);
107        /*allocate an interrupt. when does the irq become active? after leaving attach? */
108        sc->irqrid = 0;
109        if(!(sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqrid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE))){
110                device_printf(dev, "irq allocation failed\n");
111                goto error;
112        }
113	if(bus_setup_intr(dev, sc->irqres, INTR_TYPE_BIO, sc->ips_adapter_intr, sc, &sc->irqcookie)){
114                device_printf(dev, "irq setup failed\n");
115                goto error;
116        }
117	if (bus_dma_tag_create(	/* parent    */	NULL,
118				/* alignemnt */	1,
119				/* boundary  */	0,
120				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
121				/* highaddr  */	BUS_SPACE_MAXADDR,
122				/* filter    */	NULL,
123				/* filterarg */	NULL,
124				/* maxsize   */	BUS_SPACE_MAXSIZE_32BIT,
125				/* numsegs   */	IPS_MAX_SG_ELEMENTS,
126				/* maxsegsize*/	BUS_SPACE_MAXSIZE_32BIT,
127				/* flags     */	0,
128				/* lockfunc  */ busdma_lock_mutex,
129				/* lockarg   */ &Giant,
130				&sc->adapter_dmatag) != 0) {
131                printf("IPS can't alloc dma tag\n");
132                goto error;
133        }
134	if(ips_adapter_init(sc))
135		goto error;
136        sc->configured = 1;
137        return 0;
138error:
139	ips_pci_free(sc);
140        return (ENXIO);
141}
142
143static int ips_pci_free(ips_softc_t *sc)
144{
145	if(sc->adapter_dmatag)
146		bus_dma_tag_destroy(sc->adapter_dmatag);
147	if(sc->irqcookie)
148                bus_teardown_intr(sc->dev, sc->irqres, sc->irqcookie);
149        if(sc->irqres)
150               bus_release_resource(sc->dev, SYS_RES_IRQ, sc->irqrid, sc->irqres);
151        if(sc->iores)
152                bus_release_resource(sc->dev, sc->iotype, sc->rid, sc->iores);
153	sc->configured = 0;
154	return 0;
155}
156
157static int ips_pci_detach(device_t dev)
158{
159        ips_softc_t *sc;
160        DEVICE_PRINTF(1, dev, "detaching ServeRaid\n");
161        sc = (ips_softc_t *) device_get_softc(dev);
162	if (sc->configured) {
163		sc->configured = 0;
164		ips_flush_cache(sc);
165		if(ips_adapter_free(sc))
166			return EBUSY;
167		ips_pci_free(sc);
168		mtx_destroy(&sc->cmd_mtx);
169	}
170	return 0;
171}
172
173static int ips_pci_shutdown(device_t dev)
174{
175	ips_softc_t *sc = (ips_softc_t *) device_get_softc(dev);
176	if (sc->configured) {
177		ips_flush_cache(sc);
178	}
179	return 0;
180}
181
182static device_method_t ips_driver_methods[] = {
183        DEVMETHOD(device_probe, ips_pci_probe),
184        DEVMETHOD(device_attach, ips_pci_attach),
185        DEVMETHOD(device_detach, ips_pci_detach),
186	DEVMETHOD(device_shutdown, ips_pci_shutdown),
187        {0,0}
188};
189
190static driver_t ips_pci_driver = {
191        "ips",
192        ips_driver_methods,
193        sizeof(ips_softc_t),
194};
195
196static devclass_t ips_devclass;
197DRIVER_MODULE(ips, pci, ips_pci_driver, ips_devclass, 0, 0);
198