1/* 2 * Copyright (c) 1997 by Simon Shapiro 3 * All Rights Reserved
| 1/*- 2 * Copyright (c) 2000 Matthew N. Dodd <winter@jurai.net> 3 * All rights reserved.
|
4 *
| 4 *
|
| 5 * Copyright (c) 1997 Simon Shapiro 6 * All Rights Reserved 7 *
|
5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright
| 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright
|
9 * notice, this list of conditions, and the following disclaimer, 10 * without modification, immediately at the beginning of the file.
| 12 * 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.
| 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution.
|
14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission.
| |
16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
| 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
| 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 *
| 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 *
|
| 29 * $FreeBSD: head/sys/dev/dpt/dpt_pci.c 59078 2000-04-07 02:50:24Z mdodd $
|
29 */ 30
| 30 */ 31
|
31/* 32 * dptpci.c: PCI Bus Attachment for DPT SCSI HBAs 33 */ 34 35#ident "$FreeBSD: head/sys/dev/dpt/dpt_pci.c 52044 1999-10-09 03:46:28Z mdodd $" 36 37#include "opt_dpt.h" 38
| |
39#include <sys/param.h> 40#include <sys/systm.h>
| 32#include <sys/param.h> 33#include <sys/systm.h>
|
41#include <sys/malloc.h> 42#include <sys/buf.h>
| |
43#include <sys/kernel.h>
| 34#include <sys/kernel.h>
|
| 35#include <sys/module.h> 36#include <sys/bus.h>
|
44
| 37
|
45#include <pci/pcireg.h> 46#include <pci/pcivar.h> 47
| |
48#include <machine/bus_memio.h> 49#include <machine/bus_pio.h> 50#include <machine/bus.h>
| 38#include <machine/bus_memio.h> 39#include <machine/bus_pio.h> 40#include <machine/bus.h>
|
| 41#include <machine/resource.h> 42#include <sys/rman.h>
|
51
| 43
|
| 44#include <pci/pcireg.h> 45#include <pci/pcivar.h> 46
|
52#include <cam/scsi/scsi_all.h> 53 54#include <dev/dpt/dpt.h>
| 47#include <cam/scsi/scsi_all.h> 48 49#include <dev/dpt/dpt.h>
|
55#include <dev/dpt/dpt_pci.h>
| |
56
| 50
|
57#define PCI_BASEADR0 PCI_MAP_REG_START /* I/O Address */ 58#define PCI_BASEADR1 PCI_MAP_REG_START + 4 /* Mem I/O Address */
| 51#define DPT_VENDOR_ID 0x1044 52#define DPT_DEVICE_ID 0xa400
|
59
| 53
|
60#define ISA_PRIMARY_WD_ADDRESS 0x1f8
| 54#define DPT_PCI_IOADDR PCIR_MAPS /* I/O Address */ 55#define DPT_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */
|
61
| 56
|
62/* Global variables */
| 57#define ISA_PRIMARY_WD_ADDRESS 0x1f8
|
63
| 58
|
64/* Function Prototypes */
| 59static int dpt_pci_probe (device_t); 60static int dpt_pci_attach (device_t);
|
65
| 61
|
66static const char *dpt_pci_probe(pcici_t tag, pcidi_t type); 67static void dpt_pci_attach(pcici_t config_id, int unit);
| 62static int 63dpt_pci_probe (device_t dev) 64{ 65 if ((pci_get_vendor(dev) == DPT_VENDOR_ID) && 66 (pci_get_device(dev) == DPT_DEVICE_ID)) { 67 device_set_desc(dev, "DPT Caching SCSI RAID Controller"); 68 return (0); 69 } 70 return (ENXIO); 71}
|
68
| 72
|
69extern struct cdevsw dpt_cdevsw; 70 71static struct pci_device dpt_pci_driver =
| 73static int 74dpt_pci_attach (device_t dev)
|
72{
| 75{
|
73 "dpt", 74 dpt_pci_probe, 75 dpt_pci_attach, 76 &dpt_unit, 77 NULL 78};
| 76 dpt_softc_t * dpt; 77 struct resource *io = 0; 78 struct resource *irq = 0; 79 int s; 80 int rid; 81 void * ih; 82 int error = 0;
|
79
| 83
|
80COMPAT_PCI_DRIVER(dpt_pci, dpt_pci_driver);
| 84 int iotype = 0; 85 u_int32_t command;
|
81
| 86
|
82/* 83 * Probe the PCI device. 84 * Some of this work will have to be duplicated in _attach 85 * because we do not know for sure how the two relate. 86 */
| 87 command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1);
|
87
| 88
|
88static const char * 89dpt_pci_probe(pcici_t tag, pcidi_t type) 90{ 91 u_int32_t class; 92 93#ifndef PCI_COMMAND_MASTER_ENABLE 94#define PCI_COMMAND_MASTER_ENABLE 0x00000004
| 89#ifdef DPT_ALLOW_MMIO 90 if ((command & PCIM_CMD_MEMEN) != 0) { 91 rid = DPT_PCI_MEMADDR; 92 iotype = SYS_RES_MEMORY; 93 io = bus_alloc_resource(dev, iotype, &rid, 0, ~0, 1, RF_ACTIVE); 94 }
|
95#endif
| 95#endif
|
| 96 if (io == NULL && (command & PCI_COMMAND_IO_ENABLE) != 0) { 97 rid = DPT_PCI_IOADDR; 98 iotype = SYS_RES_IOPORT; 99 io = bus_alloc_resource(dev, iotype, &rid, 0, ~0, 1, RF_ACTIVE); 100 }
|
96
| 101
|
97#ifndef PCI_SUBCLASS_MASS_STORAGE_SCSI 98#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00000000 99#endif
| 102 if (io == NULL) { 103 device_printf(dev, "can't allocate register resources\n"); 104 error = ENOMEM; 105 goto bad; 106 }
|
100
| 107
|
101 class = pci_conf_read(tag, PCI_CLASS_REG); 102 if (((type & 0xffff0000) >> 16) == DPT_DEVICE_ID 103 && (class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE 104 && (class & PCI_SUBCLASS_MASK) == PCI_SUBCLASS_MASS_STORAGE_SCSI) 105 return ("DPT Caching SCSI RAID Controller"); 106 return (NULL); 107}
| 108 rid = 0; 109 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE); 110 if (!irq) { 111 device_printf(dev, "No irq?!\n"); 112 error = ENOMEM; 113 goto bad; 114 }
|
108
| 115
|
109static void 110dpt_pci_attach(pcici_t config_id, int unit) 111{ 112 dpt_softc_t *dpt; 113 vm_offset_t vaddr; 114#ifdef DPT_ALLOW_MEMIO 115 vm_offset_t paddr; 116#endif 117 u_int16_t io_base; 118 bus_space_tag_t tag; 119 bus_space_handle_t bsh; 120 u_int32_t command; 121 int s;
| 116 /* Ensure busmastering is enabled */ 117 command |= PCIM_CMD_BUSMASTEREN; 118 pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1);
|
122
| 119
|
123 vaddr = NULL; 124 command = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); 125#ifdef DPT_ALLOW_MEMIO 126 if ((command & PCI_COMMAND_MEM_ENABLE) == 0 127 || (pci_map_mem(config_id, PCI_BASEADR1, &vaddr, &paddr)) == 0) 128#endif 129 if ((command & PCI_COMMAND_IO_ENABLE) == 0 130 || (pci_map_port(config_id, PCI_BASEADR0, &io_base)) == 0) 131 return; 132 133 /* 134 * If the DPT is mapped as an IDE controller, 135 * let it be IDE controller 136 */ 137 if (io_base == ISA_PRIMARY_WD_ADDRESS - 0x10) {
| 120 if (rman_get_start(io) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) {
|
138#ifdef DPT_DEBUG_WARN
| 121#ifdef DPT_DEBUG_WARN
|
139 printf("dpt%d: Mapped as an IDE controller. " 140 "Disabling SCSI setup\n", unit);
| 122 device_printf(dev, "Mapped as an IDE controller. " 123 "Disabling SCSI setup\n");
|
141#endif
| 124#endif
|
142 return;
| 125 error = ENXIO; 126 goto bad;
|
143 } 144
| 127 } 128
|
145 /* XXX Should be passed in by parent bus */ 146 /* XXX Why isn't the 0x10 offset incorporated into the reg defs? */ 147 if (vaddr != 0) { 148 tag = I386_BUS_SPACE_MEM; 149 bsh = vaddr + 0x10; 150 } else { 151 tag = I386_BUS_SPACE_IO; 152 bsh = io_base + 0x10;
| 129 dpt = dpt_alloc(dev, rman_get_bustag(io), rman_get_bushandle(io)); 130 if (dpt == NULL) { 131 error = ENXIO; 132 goto bad;
|
153 } 154
| 133 } 134
|
155 if ((dpt = dpt_alloc(unit, tag, bsh)) == NULL) 156 return; /* XXX PCI code should take return status */ 157
| |
158 /* Allocate a dmatag representing the capabilities of this attachment */ 159 /* XXX Should be a child of the PCI bus dma tag */
| 135 /* Allocate a dmatag representing the capabilities of this attachment */ 136 /* XXX Should be a child of the PCI bus dma tag */
|
160 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/1, /*boundary*/0, 161 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 162 /*highaddr*/BUS_SPACE_MAXADDR, 163 /*filter*/NULL, /*filterarg*/NULL, 164 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 165 /*nsegments*/BUS_SPACE_UNRESTRICTED, 166 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 167 /*flags*/0, &dpt->parent_dmat) != 0) {
| 137 if (bus_dma_tag_create( /* parent */ NULL, 138 /* alignemnt */ 1, 139 /* boundary */ 0, 140 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 141 /* highaddr */ BUS_SPACE_MAXADDR, 142 /* filter */ NULL, 143 /* filterarg */ NULL, 144 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 145 /* nsegments */ BUS_SPACE_UNRESTRICTED, 146 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 147 /* flags */ 0, 148 &dpt->parent_dmat) != 0) {
|
168 dpt_free(dpt);
| 149 dpt_free(dpt);
|
169 return;
| 150 error = ENXIO; 151 goto bad;
|
170 } 171
| 152 } 153
|
172 if (pci_map_int(config_id, dpt_intr, (void *)dpt, &cam_imask) == 0) { 173 dpt_free(dpt); 174 return; 175 } 176
| |
177 s = splcam();
| 154 s = splcam();
|
| 155
|
178 if (dpt_init(dpt) != 0) { 179 dpt_free(dpt);
| 156 if (dpt_init(dpt) != 0) { 157 dpt_free(dpt);
|
180 return;
| 158 error = ENXIO; 159 goto bad;
|
181 } 182 183 /* Register with the XPT */ 184 dpt_attach(dpt);
| 160 } 161 162 /* Register with the XPT */ 163 dpt_attach(dpt);
|
| 164
|
185 splx(s);
| 165 splx(s);
|
| 166 167 if (bus_setup_intr(dev, irq, INTR_TYPE_CAM, dpt_intr, dpt, &ih)) { 168 device_printf(dev, "Unable to register interrupt handler\n"); 169 error = ENXIO; 170 goto bad; 171 } 172 173 return (error); 174 175bad: 176 if (io) 177 bus_release_resource(dev, iotype, 0, io); 178 if (irq) 179 bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 180 181 return (error);
|
186}
| 182}
|
| 183 184static device_method_t dpt_pci_methods[] = { 185 /* Device interface */ 186 DEVMETHOD(device_probe, dpt_pci_probe), 187 DEVMETHOD(device_attach, dpt_pci_attach), 188 189 { 0, 0 } 190}; 191 192static driver_t dpt_pci_driver = { 193 "dpt", 194 dpt_pci_methods, 195 sizeof(dpt_softc_t), 196}; 197 198static devclass_t dpt_devclass; 199 200DRIVER_MODULE(dpt, pci, dpt_pci_driver, dpt_devclass, 0, 0);
|
| |