2 * Copyright (c) 1999,2000 Jonathan Lemon
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/ida/ida_pci.c,v 1.7.2.7 2001/07/30 20:29:58 jlemon Exp $
27 * $DragonFly: src/sys/dev/raid/ida/ida_pci.c,v 1.6 2006/10/25 22:56:01 dillon Exp $
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/malloc.h>
33 #include <sys/kernel.h>
37 #include <sys/devicestat.h>
41 #include <bus/pci/pcireg.h>
42 #include <bus/pci/pcivar.h>
47 #define IDA_PCI_MAX_DMA_ADDR 0xFFFFFFFF
48 #define IDA_PCI_MAX_DMA_COUNT 0xFFFFFFFF
50 #define IDA_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */
52 #define IDA_DEVICEID_SMART 0xAE100E11
53 #define IDA_DEVICEID_DEC_SMART 0x00461011
54 #define IDA_DEVICEID_NCR_53C1510 0x00101000
57 ida_v3_fifo_full(struct ida_softc
*ida
)
59 return (ida_inl(ida
, R_CMD_FIFO
) == 0);
63 ida_v3_submit(struct ida_softc
*ida
, struct ida_qcb
*qcb
)
65 ida_outl(ida
, R_CMD_FIFO
, qcb
->hwqcb_busaddr
);
69 ida_v3_done(struct ida_softc
*ida
)
71 return (ida_inl(ida
, R_DONE_FIFO
));
75 ida_v3_int_pending(struct ida_softc
*ida
)
77 return (ida_inl(ida
, R_INT_PENDING
));
81 ida_v3_int_enable(struct ida_softc
*ida
, int enable
)
84 ida
->flags
|= IDA_INTERRUPTS
;
86 ida
->flags
&= ~IDA_INTERRUPTS
;
87 ida_outl(ida
, R_INT_MASK
, enable
? INT_ENABLE
: INT_DISABLE
);
91 ida_v4_fifo_full(struct ida_softc
*ida
)
93 return (ida_inl(ida
, R_42XX_REQUEST
) != 0);
97 ida_v4_submit(struct ida_softc
*ida
, struct ida_qcb
*qcb
)
99 ida_outl(ida
, R_42XX_REQUEST
, qcb
->hwqcb_busaddr
);
103 ida_v4_done(struct ida_softc
*ida
)
105 bus_addr_t completed
;
107 completed
= ida_inl(ida
, R_42XX_REPLY
);
109 return (0); /* fifo is empty */
110 ida_outl(ida
, R_42XX_REPLY
, 0); /* confirm read */
115 ida_v4_int_pending(struct ida_softc
*ida
)
117 return (ida_inl(ida
, R_42XX_STATUS
) & STATUS_42XX_INT_PENDING
);
121 ida_v4_int_enable(struct ida_softc
*ida
, int enable
)
124 ida
->flags
|= IDA_INTERRUPTS
;
126 ida
->flags
&= ~IDA_INTERRUPTS
;
127 ida_outl(ida
, R_42XX_INT_MASK
,
128 enable
? INT_ENABLE_42XX
: INT_DISABLE_42XX
);
131 static struct ida_access ida_v3_access
= {
139 static struct ida_access ida_v4_access
= {
147 static struct ida_board board_id
[] = {
148 { 0x40300E11, "Compaq SMART-2/P array controller",
150 { 0x40310E11, "Compaq SMART-2SL array controller",
152 { 0x40320E11, "Compaq Smart Array 3200 controller",
154 { 0x40330E11, "Compaq Smart Array 3100ES controller",
156 { 0x40340E11, "Compaq Smart Array 221 controller",
159 { 0x40400E11, "Compaq Integrated Array controller",
160 &ida_v4_access
, IDA_FIRMWARE
},
161 { 0x40480E11, "Compaq RAID LC2 controller",
162 &ida_v4_access
, IDA_FIRMWARE
},
163 { 0x40500E11, "Compaq Smart Array 4200 controller",
165 { 0x40510E11, "Compaq Smart Array 4250ES controller",
167 { 0x40580E11, "Compaq Smart Array 431 controller",
173 static int ida_pci_probe(device_t dev
);
174 static int ida_pci_attach(device_t dev
);
176 static device_method_t ida_pci_methods
[] = {
177 DEVMETHOD(device_probe
, ida_pci_probe
),
178 DEVMETHOD(device_attach
, ida_pci_attach
),
179 DEVMETHOD(device_detach
, ida_detach
),
181 DEVMETHOD(bus_print_child
, bus_generic_print_child
),
186 static driver_t ida_pci_driver
= {
189 sizeof(struct ida_softc
)
192 static devclass_t ida_devclass
;
194 static struct ida_board
*
195 ida_pci_match(device_t dev
)
198 u_int32_t id
, sub_id
;
200 id
= pci_get_devid(dev
);
201 sub_id
= pci_get_subdevice(dev
) << 16 | pci_get_subvendor(dev
);
203 if (id
== IDA_DEVICEID_SMART
||
204 id
== IDA_DEVICEID_DEC_SMART
||
205 id
== IDA_DEVICEID_NCR_53C1510
) {
206 for (i
= 0; board_id
[i
].board
; i
++)
207 if (board_id
[i
].board
== sub_id
)
208 return (&board_id
[i
]);
214 ida_pci_probe(device_t dev
)
216 struct ida_board
*board
= ida_pci_match(dev
);
219 device_set_desc(dev
, board
->desc
);
226 ida_pci_attach(device_t dev
)
228 struct ida_board
*board
= ida_pci_match(dev
);
229 u_int32_t id
= pci_get_devid(dev
);
230 struct ida_softc
*ida
;
234 command
= pci_read_config(dev
, PCIR_COMMAND
, 1);
237 * it appears that this board only does MEMIO access.
239 if ((command
& PCIM_CMD_MEMEN
) == 0) {
240 device_printf(dev
, "Only memory mapped I/O is supported\n");
244 ida
= (struct ida_softc
*)device_get_softc(dev
);
246 ida
->cmd
= *board
->accessor
;
247 ida
->flags
= board
->flags
;
249 ida
->regs_res_type
= SYS_RES_MEMORY
;
250 ida
->regs_res_id
= IDA_PCI_MEMADDR
;
251 if (id
== IDA_DEVICEID_DEC_SMART
)
252 ida
->regs_res_id
= PCIR_MAPS
;
254 ida
->regs
= bus_alloc_resource(dev
, ida
->regs_res_type
,
255 &ida
->regs_res_id
, 0, ~0, 1, RF_ACTIVE
);
256 if (ida
->regs
== NULL
) {
257 device_printf(dev
, "can't allocate memory resources\n");
261 error
= bus_dma_tag_create(/*parent*/NULL
, /*alignment*/1,
262 /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT
,
263 /*highaddr*/BUS_SPACE_MAXADDR
, /*filter*/NULL
, /*filterarg*/NULL
,
264 /*maxsize*/MAXBSIZE
, /*nsegments*/IDA_NSEG
,
265 /*maxsegsize*/BUS_SPACE_MAXSIZE_32BIT
, /*flags*/BUS_DMA_ALLOCNOW
,
268 device_printf(dev
, "can't allocate DMA tag\n");
274 ida
->irq_res_type
= SYS_RES_IRQ
;
275 ida
->irq
= bus_alloc_resource(dev
, ida
->irq_res_type
, &rid
,
276 0, ~0, 1, RF_ACTIVE
| RF_SHAREABLE
);
277 if (ida
->irq
== NULL
) {
281 error
= bus_setup_intr(dev
, ida
->irq
, 0,
282 ida_intr
, ida
, &ida
->ih
, NULL
);
284 device_printf(dev
, "can't setup interrupt\n");
289 error
= ida_init(ida
);
295 ida
->flags
|= IDA_ATTACHED
;
300 DRIVER_MODULE(ida
, pci
, ida_pci_driver
, ida_devclass
, 0, 0);