icp_pci.c revision 1.1 1 /* $NetBSD: icp_pci.c,v 1.1 2002/04/22 21:05:21 ad Exp $ */
2
3 /*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by Niklas Hallqvist.
53 * 4. The name of the author may not be used to endorse or promote products
54 * derived from this software without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
57 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
58 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
59 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
60 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
61 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
62 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
63 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
64 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
65 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66 *
67 * from OpenBSD: icp_pci.c,v 1.11 2001/06/12 15:40:30 niklas Exp
68 */
69
70 /*
71 * This driver would not have written if it was not for the hardware donations
72 * from both ICP-Vortex and ko.neT. I want to thank them for their support.
73 *
74 * Re-worked for NetBSD by Andrew Doran. Test hardware kindly supplied by
75 * Intel.
76 */
77
78 #include <sys/cdefs.h>
79 __KERNEL_RCSID(0, "$NetBSD: icp_pci.c,v 1.1 2002/04/22 21:05:21 ad Exp $");
80
81 #include <sys/param.h>
82 #include <sys/systm.h>
83 #include <sys/device.h>
84 #include <sys/kernel.h>
85 #include <sys/queue.h>
86 #include <sys/buf.h>
87 #include <sys/endian.h>
88 #include <sys/conf.h>
89
90 #include <uvm/uvm_extern.h>
91
92 #include <machine/bus.h>
93
94 #include <dev/pci/pcireg.h>
95 #include <dev/pci/pcivar.h>
96 #include <dev/pci/pcidevs.h>
97
98 #include <dev/ic/icpreg.h>
99 #include <dev/ic/icpvar.h>
100
101 /* Product numbers for Fibre-Channel are greater than or equal to 0x200 */
102 #define ICP_PCI_PRODUCT_FC 0x200
103
104 /* Mapping registers for various areas */
105 #define ICP_PCI_DPMEM 0x10
106 #define ICP_PCINEW_IOMEM 0x10
107 #define ICP_PCINEW_IO 0x14
108 #define ICP_PCINEW_DPMEM 0x18
109
110 /* PCI SRAM structure */
111 #define ICP_MAGIC 0x00 /* u_int32_t, controller ID from BIOS */
112 #define ICP_NEED_DEINIT 0x04 /* u_int16_t, switch between BIOS/driver */
113 #define ICP_SWITCH_SUPPORT 0x06 /* u_int8_t, see ICP_NEED_DEINIT */
114 #define ICP_OS_USED 0x10 /* u_int8_t [16], OS code per service */
115 #define ICP_FW_MAGIC 0x3c /* u_int8_t, controller ID from firmware */
116 #define ICP_SRAM_SZ 0x40
117
118 /* DPRAM PCI controllers */
119 #define ICP_DPR_IF 0x00 /* interface area */
120 #define ICP_6SR (0xff0 - ICP_SRAM_SZ)
121 #define ICP_SEMA1 0xff1 /* volatile u_int8_t, command semaphore */
122 #define ICP_IRQEN 0xff5 /* u_int8_t, board interrupts enable */
123 #define ICP_EVENT 0xff8 /* u_int8_t, release event */
124 #define ICP_IRQDEL 0xffc /* u_int8_t, acknowledge board interrupt */
125 #define ICP_DPRAM_SZ 0x1000
126
127 /* PLX register structure (new PCI controllers) */
128 #define ICP_CFG_REG 0x00 /* u_int8_t, DPRAM cfg. (2: < 1MB, 0: any) */
129 #define ICP_SEMA0_REG 0x40 /* volatile u_int8_t, command semaphore */
130 #define ICP_SEMA1_REG 0x41 /* volatile u_int8_t, status semaphore */
131 #define ICP_PLX_STATUS 0x44 /* volatile u_int16_t, command status */
132 #define ICP_PLX_SERVICE 0x46 /* u_int16_t, service */
133 #define ICP_PLX_INFO 0x48 /* u_int32_t [2], additional info */
134 #define ICP_LDOOR_REG 0x60 /* u_int8_t, PCI to local doorbell */
135 #define ICP_EDOOR_REG 0x64 /* volatile u_int8_t, local to PCI doorbell */
136 #define ICP_CONTROL0 0x68 /* u_int8_t, control0 register (unused) */
137 #define ICP_CONTROL1 0x69 /* u_int8_t, board interrupts enable */
138 #define ICP_PLX_SZ 0x80
139
140 /* DPRAM new PCI controllers */
141 #define ICP_IC 0x00 /* interface */
142 #define ICP_PCINEW_6SR (0x4000 - ICP_SRAM_SZ)
143 /* SRAM structure */
144 #define ICP_PCINEW_SZ 0x4000
145
146 /* i960 register structure (PCI MPR controllers) */
147 #define ICP_MPR_SEMA0 0x10 /* volatile u_int8_t, command semaphore */
148 #define ICP_MPR_SEMA1 0x12 /* volatile u_int8_t, status semaphore */
149 #define ICP_MPR_STATUS 0x14 /* volatile u_int16_t, command status */
150 #define ICP_MPR_SERVICE 0x16 /* u_int16_t, service */
151 #define ICP_MPR_INFO 0x18 /* u_int32_t [2], additional info */
152 #define ICP_MPR_LDOOR 0x20 /* u_int8_t, PCI to local doorbell */
153 #define ICP_MPR_EDOOR 0x2c /* volatile u_int8_t, locl to PCI doorbell */
154 #define ICP_EDOOR_EN 0x34 /* u_int8_t, board interrupts enable */
155 #define ICP_I960_SZ 0x1000
156
157 /* DPRAM PCI MPR controllers */
158 #define ICP_I960R 0x00 /* 4KB i960 registers */
159 #define ICP_MPR_IC ICP_I960_SZ
160 /* interface area */
161 #define ICP_MPR_6SR (ICP_I960_SZ + 0x3000 - ICP_SRAM_SZ)
162 /* SRAM structure */
163 #define ICP_MPR_SZ 0x4000
164
165 int icp_pci_match(struct device *, struct cfdata *, void *);
166 void icp_pci_attach(struct device *, struct device *, void *);
167 void icp_pci_enable_intr(struct icp_softc *);
168 const struct icp_pci_ident *icp_pci_find_ident(struct pci_attach_args *);
169
170 void icp_pci_copy_cmd(struct icp_softc *, struct icp_ccb *);
171 u_int8_t icp_pci_get_status(struct icp_softc *);
172 void icp_pci_intr(struct icp_softc *, struct icp_intr_ctx *);
173 void icp_pci_release_event(struct icp_softc *, struct icp_ccb *);
174 void icp_pci_set_sema0(struct icp_softc *);
175 int icp_pci_test_busy(struct icp_softc *);
176
177 void icp_pcinew_copy_cmd(struct icp_softc *, struct icp_ccb *);
178 u_int8_t icp_pcinew_get_status(struct icp_softc *);
179 void icp_pcinew_intr(struct icp_softc *, struct icp_intr_ctx *);
180 void icp_pcinew_release_event(struct icp_softc *, struct icp_ccb *);
181 void icp_pcinew_set_sema0(struct icp_softc *);
182 int icp_pcinew_test_busy(struct icp_softc *);
183
184 void icp_mpr_copy_cmd(struct icp_softc *, struct icp_ccb *);
185 u_int8_t icp_mpr_get_status(struct icp_softc *);
186 void icp_mpr_intr(struct icp_softc *, struct icp_intr_ctx *);
187 void icp_mpr_release_event(struct icp_softc *, struct icp_ccb *);
188 void icp_mpr_set_sema0(struct icp_softc *);
189 int icp_mpr_test_busy(struct icp_softc *);
190
191 struct cfattach icp_pci_ca = {
192 sizeof(struct icp_softc), icp_pci_match, icp_pci_attach
193 };
194
195 struct icp_pci_ident {
196 u_short gpi_vendor;
197 u_short gpi_product;
198 u_short gpi_class;
199 } const icp_pci_ident[] = {
200 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_60x0, ICP_PCI },
201 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6000B, ICP_PCI },
202
203 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x10, ICP_PCINEW },
204 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x20, ICP_PCINEW },
205 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6530, ICP_PCINEW },
206 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6550, ICP_PCINEW },
207 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x17, ICP_PCINEW },
208 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x27, ICP_PCINEW },
209 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6537, ICP_PCINEW },
210 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6557, ICP_PCINEW },
211 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x15, ICP_PCINEW },
212 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x25, ICP_PCINEW },
213 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6535, ICP_PCINEW },
214 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6555, ICP_PCINEW },
215
216 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x17RP, ICP_MPR },
217 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x27RP, ICP_MPR },
218 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6537RP, ICP_MPR },
219 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6557RP, ICP_MPR },
220 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x11RP, ICP_MPR },
221 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x21RP, ICP_MPR },
222 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x17RD, ICP_MPR },
223 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x27RD, ICP_MPR },
224 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6537RD, ICP_MPR },
225 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6557RD, ICP_MPR },
226 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x11RD, ICP_MPR },
227 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x21RD, ICP_MPR },
228 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x18RD, ICP_MPR },
229 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x28RD, ICP_MPR },
230 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x38RD, ICP_MPR },
231 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x58RD, ICP_MPR },
232 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6518RS, ICP_MPR },
233 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x18RN, ICP_MPR },
234 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x28RN, ICP_MPR },
235 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x38RN, ICP_MPR },
236 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x58RN, ICP_MPR },
237 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x19RD, ICP_MPR },
238 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_6x29RD, ICP_MPR },
239 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x19RN, ICP_MPR },
240 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x29RN, ICP_MPR },
241 { PCI_VENDOR_VORTEX, PCI_PRODUCT_VORTEX_GDT_7x43RN, ICP_MPR },
242
243 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_GDT_RAID1, ICP_MPR },
244 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_GDT_RAID2, ICP_MPR },
245 };
246
247 const struct icp_pci_ident *
248 icp_pci_find_ident(struct pci_attach_args *pa)
249 {
250 const struct icp_pci_ident *gpi, *maxgpi;
251
252 gpi = icp_pci_ident;
253 maxgpi = gpi + sizeof(icp_pci_ident) / sizeof(icp_pci_ident[0]);
254
255 for (; gpi < maxgpi; gpi++)
256 if (PCI_VENDOR(pa->pa_id) == gpi->gpi_vendor &&
257 PCI_PRODUCT(pa->pa_id) == gpi->gpi_product)
258 return (gpi);
259
260 return (NULL);
261 }
262
263 int
264 icp_pci_match(struct device *parent, struct cfdata *match, void *aux)
265 {
266 struct pci_attach_args *pa;
267
268 pa = aux;
269
270 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O)
271 return (0);
272
273 return (icp_pci_find_ident(pa) != NULL);
274 }
275
276 void
277 icp_pci_attach(struct device *parent, struct device *self, void *aux)
278 {
279 struct pci_attach_args *pa;
280 struct icp_softc *icp;
281 bus_space_tag_t dpmemt, iomemt, iot;
282 bus_space_handle_t dpmemh, iomemh, ioh;
283 bus_addr_t dpmembase, iomembase, iobase;
284 bus_size_t dpmemsize, iomemsize, iosize;
285 u_int16_t prod;
286 u_int32_t status = 0;
287 #define DPMEM_MAPPED 1
288 #define IOMEM_MAPPED 2
289 #define IO_MAPPED 4
290 #define INTR_ESTABLISHED 8
291 int retries;
292 u_int8_t protocol;
293 pci_intr_handle_t ih;
294 const char *intrstr;
295 const struct icp_pci_ident *gpi;
296
297 printf(": ");
298
299 pa = aux;
300 icp = (struct icp_softc *)self;
301
302 prod = PCI_PRODUCT(pa->pa_id);
303 gpi = icp_pci_find_ident(pa);
304 icp->icp_class = gpi->gpi_class;
305
306 /* If we don't recognize it, determine class heuristically. */
307 if (icp->icp_class == 0)
308 icp->icp_class = prod < 0x100 ? ICP_PCINEW : ICP_MPR;
309
310 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL &&
311 prod >= ICP_PCI_PRODUCT_FC)
312 icp->icp_class |= ICP_FC;
313
314 if (pci_mapreg_map(pa,
315 ICP_CLASS(icp) == ICP_PCINEW ? ICP_PCINEW_DPMEM : ICP_PCI_DPMEM,
316 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &dpmemt,
317 &dpmemh, &dpmembase, &dpmemsize)) {
318 if (pci_mapreg_map(pa,
319 ICP_CLASS(icp) == ICP_PCINEW ? ICP_PCINEW_DPMEM :
320 ICP_PCI_DPMEM,
321 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT_1M, 0,
322 &dpmemt, &dpmemh, &dpmembase, &dpmemsize)) {
323 printf("cannot map DPMEM\n");
324 goto bail_out;
325 }
326 }
327 status |= DPMEM_MAPPED;
328 icp->icp_dpmemt = dpmemt;
329 icp->icp_dpmemh = dpmemh;
330 icp->icp_dpmembase = dpmembase;
331 icp->icp_dmat = pa->pa_dmat;
332
333 /*
334 * The ICP_PCINEW series also has two other regions to map.
335 */
336 if (ICP_CLASS(icp) == ICP_PCINEW) {
337 if (pci_mapreg_map(pa, ICP_PCINEW_IOMEM, PCI_MAPREG_TYPE_MEM,
338 0, &iomemt, &iomemh, &iomembase, &iomemsize)) {
339 printf("cannot map memory mapped I/O ports\n");
340 goto bail_out;
341 }
342 status |= IOMEM_MAPPED;
343
344 if (pci_mapreg_map(pa, ICP_PCINEW_IO, PCI_MAPREG_TYPE_IO, 0,
345 &iot, &ioh, &iobase, &iosize)) {
346 printf("cannot map I/O ports\n");
347 goto bail_out;
348 }
349 status |= IO_MAPPED;
350 icp->icp_iot = iot;
351 icp->icp_ioh = ioh;
352 icp->icp_iobase = iobase;
353 }
354
355 switch (ICP_CLASS(icp)) {
356 case ICP_PCI:
357 bus_space_set_region_4(dpmemt, dpmemh, 0, 0,
358 ICP_DPR_IF_SZ >> 2);
359 if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) {
360 printf("cannot write to DPMEM\n");
361 goto bail_out;
362 }
363
364 #if 0
365 /* disable board interrupts, deinit services */
366 icph_writeb(0xff, &dp6_ptr->io.irqdel);
367 icph_writeb(0x00, &dp6_ptr->io.irqen);;
368 icph_writeb(0x00, &dp6_ptr->u.ic.S_Status);
369 icph_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
370
371 icph_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
372 icph_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
373 icph_writeb(0, &dp6_ptr->io.event);
374 retries = INIT_RETRIES;
375 icph_delay(20);
376 while (icph_readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
377 if (--retries == 0) {
378 printk("initialization error (DEINIT failed)\n");
379 icph_munmap(ha->brd);
380 return 0;
381 }
382 icph_delay(1);
383 }
384 prot_ver = (unchar)icph_readl(&dp6_ptr->u.ic.S_Info[0]);
385 icph_writeb(0, &dp6_ptr->u.ic.S_Status);
386 icph_writeb(0xff, &dp6_ptr->io.irqdel);
387 if (prot_ver != PROTOCOL_VERSION) {
388 printk("illegal protocol version\n");
389 icph_munmap(ha->brd);
390 return 0;
391 }
392
393 ha->type = ICP_PCI;
394 ha->ic_all_size = sizeof(dp6_ptr->u);
395
396 /* special command to controller BIOS */
397 icph_writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
398 icph_writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
399 icph_writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
400 icph_writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
401 icph_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
402 icph_writeb(0, &dp6_ptr->io.event);
403 retries = INIT_RETRIES;
404 icph_delay(20);
405 while (icph_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
406 if (--retries == 0) {
407 printk("initialization error\n");
408 icph_munmap(ha->brd);
409 return 0;
410 }
411 icph_delay(1);
412 }
413 icph_writeb(0, &dp6_ptr->u.ic.S_Status);
414 icph_writeb(0xff, &dp6_ptr->io.irqdel);
415 #endif
416
417 icp->icp_ic_all_size = ICP_DPRAM_SZ;
418
419 icp->icp_copy_cmd = icp_pci_copy_cmd;
420 icp->icp_get_status = icp_pci_get_status;
421 icp->icp_intr = icp_pci_intr;
422 icp->icp_release_event = icp_pci_release_event;
423 icp->icp_set_sema0 = icp_pci_set_sema0;
424 icp->icp_test_busy = icp_pci_test_busy;
425
426 break;
427
428 case ICP_PCINEW:
429 bus_space_set_region_4(dpmemt, dpmemh, 0, 0,
430 ICP_DPR_IF_SZ >> 2);
431 if (bus_space_read_1(dpmemt, dpmemh, 0) != 0) {
432 printf("cannot write to DPMEM\n");
433 goto bail_out;
434 }
435
436 #if 0
437 /* disable board interrupts, deinit services */
438 outb(0x00,PTR2USHORT(&ha->plx->control1));
439 outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
440
441 icph_writeb(0x00, &dp6c_ptr->u.ic.S_Status);
442 icph_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
443
444 icph_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
445 icph_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
446
447 outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
448
449 retries = INIT_RETRIES;
450 icph_delay(20);
451 while (icph_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
452 if (--retries == 0) {
453 printk("initialization error (DEINIT failed)\n");
454 icph_munmap(ha->brd);
455 return 0;
456 }
457 icph_delay(1);
458 }
459 prot_ver = (unchar)icph_readl(&dp6c_ptr->u.ic.S_Info[0]);
460 icph_writeb(0, &dp6c_ptr->u.ic.Status);
461 if (prot_ver != PROTOCOL_VERSION) {
462 printk("illegal protocol version\n");
463 icph_munmap(ha->brd);
464 return 0;
465 }
466
467 ha->type = ICP_PCINEW;
468 ha->ic_all_size = sizeof(dp6c_ptr->u);
469
470 /* special command to controller BIOS */
471 icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
472 icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
473 icph_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
474 icph_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
475 icph_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
476
477 outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
478
479 retries = INIT_RETRIES;
480 icph_delay(20);
481 while (icph_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
482 if (--retries == 0) {
483 printk("initialization error\n");
484 icph_munmap(ha->brd);
485 return 0;
486 }
487 icph_delay(1);
488 }
489 icph_writeb(0, &dp6c_ptr->u.ic.S_Status);
490 #endif
491
492 icp->icp_ic_all_size = ICP_PCINEW_SZ;
493
494 icp->icp_copy_cmd = icp_pcinew_copy_cmd;
495 icp->icp_get_status = icp_pcinew_get_status;
496 icp->icp_intr = icp_pcinew_intr;
497 icp->icp_release_event = icp_pcinew_release_event;
498 icp->icp_set_sema0 = icp_pcinew_set_sema0;
499 icp->icp_test_busy = icp_pcinew_test_busy;
500
501 break;
502
503 case ICP_MPR:
504 bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC, ICP_MPR_MAGIC);
505 if (bus_space_read_4(dpmemt, dpmemh, ICP_MPR_IC) !=
506 ICP_MPR_MAGIC) {
507 printf("cannot access DPMEM at 0x%lx (shadowed?)\n",
508 (u_long)dpmembase);
509 goto bail_out;
510 }
511
512 /*
513 * XXX Here the Linux driver has a weird remapping logic I
514 * don't understand. My controller does not need it, and I
515 * cannot see what purpose it serves, therefore I did not
516 * do anything similar.
517 */
518
519 bus_space_set_region_4(dpmemt, dpmemh, ICP_I960_SZ, 0,
520 ICP_DPR_IF_SZ >> 2);
521
522 /* Disable everything. */
523 bus_space_write_1(dpmemt, dpmemh, ICP_EDOOR_EN,
524 bus_space_read_1(dpmemt, dpmemh, ICP_EDOOR_EN) | 4);
525 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_EDOOR, 0xff);
526 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS,
527 0);
528 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_CMD_INDEX,
529 0);
530
531 bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO,
532 htole32(dpmembase));
533 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_CMD_INDX,
534 0xff);
535 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_LDOOR, 1);
536
537 DELAY(20);
538 retries = 1000000;
539 while (bus_space_read_1(dpmemt, dpmemh,
540 ICP_MPR_IC + ICP_S_STATUS) != 0xff) {
541 if (--retries == 0) {
542 printf("DEINIT failed\n");
543 goto bail_out;
544 }
545 DELAY(1);
546 }
547
548 protocol = (u_int8_t)bus_space_read_4(dpmemt, dpmemh,
549 ICP_MPR_IC + ICP_S_INFO);
550 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS,
551 0);
552 if (protocol != ICP_PROTOCOL_VERSION) {
553 printf("unsupported protocol %d\n", protocol);
554 goto bail_out;
555 }
556
557 /* special commnd to controller BIOS */
558 bus_space_write_4(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_INFO, 0);
559 bus_space_write_4(dpmemt, dpmemh,
560 ICP_MPR_IC + ICP_S_INFO + sizeof(u_int32_t), 0);
561 bus_space_write_4(dpmemt, dpmemh,
562 ICP_MPR_IC + ICP_S_INFO + 2 * sizeof(u_int32_t), 1);
563 bus_space_write_4(dpmemt, dpmemh,
564 ICP_MPR_IC + ICP_S_INFO + 3 * sizeof(u_int32_t), 0);
565 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_CMD_INDX,
566 0xfe);
567 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_LDOOR, 1);
568
569 DELAY(20);
570 retries = 1000000;
571 while (bus_space_read_1(dpmemt, dpmemh,
572 ICP_MPR_IC + ICP_S_STATUS) != 0xfe) {
573 if (--retries == 0) {
574 printf("initialization error\n");
575 goto bail_out;
576 }
577 DELAY(1);
578 }
579
580 bus_space_write_1(dpmemt, dpmemh, ICP_MPR_IC + ICP_S_STATUS,
581 0);
582
583 icp->icp_copy_cmd = icp_mpr_copy_cmd;
584 icp->icp_get_status = icp_mpr_get_status;
585 icp->icp_intr = icp_mpr_intr;
586 icp->icp_release_event = icp_mpr_release_event;
587 icp->icp_set_sema0 = icp_mpr_set_sema0;
588 icp->icp_test_busy = icp_mpr_test_busy;
589 break;
590 }
591
592 if (pci_intr_map(pa, &ih)) {
593 printf("couldn't map interrupt\n");
594 goto bail_out;
595 }
596 intrstr = pci_intr_string(pa->pa_pc, ih);
597 icp->icp_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, icp_intr, icp);
598 if (icp->icp_ih == NULL) {
599 printf("couldn't establish interrupt");
600 if (intrstr != NULL)
601 printf(" at %s", intrstr);
602 printf("\n");
603 goto bail_out;
604 }
605 status |= INTR_ESTABLISHED;
606
607 if (gpi->gpi_vendor == PCI_VENDOR_INTEL)
608 printf("Intel Storage RAID controller\n");
609 else
610 printf("ICP-Vortex RAID controller\n");
611
612 if (icp_init(icp, intrstr))
613 goto bail_out;
614
615 icp_pci_enable_intr(icp);
616 return;
617
618 bail_out:
619 if ((status & DPMEM_MAPPED) != 0)
620 bus_space_unmap(dpmemt, dpmemh, dpmemsize);
621 if ((status & IOMEM_MAPPED) != 0)
622 bus_space_unmap(iomemt, iomemh, iomembase);
623 if ((status & IO_MAPPED) != 0)
624 bus_space_unmap(iot, ioh, iosize);
625 if ((status & INTR_ESTABLISHED) != 0)
626 pci_intr_disestablish(pa->pa_pc, icp->icp_ih);
627 }
628
629 /*
630 * Enable interrupts.
631 */
632 void
633 icp_pci_enable_intr(struct icp_softc *icp)
634 {
635
636 switch (ICP_CLASS(icp)) {
637 case ICP_PCI:
638 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_IRQDEL,
639 1);
640 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh,
641 ICP_CMD_INDEX, 0);
642 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_IRQEN,
643 1);
644 break;
645
646 case ICP_PCINEW:
647 bus_space_write_1(icp->icp_iot, icp->icp_ioh, ICP_EDOOR_REG,
648 0xff);
649 bus_space_write_1(icp->icp_iot, icp->icp_ioh, ICP_CONTROL1, 3);
650 break;
651
652 case ICP_MPR:
653 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh,
654 ICP_MPR_EDOOR, 0xff);
655 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_EDOOR_EN,
656 bus_space_read_1(icp->icp_dpmemt, icp->icp_dpmemh,
657 ICP_EDOOR_EN) & ~4);
658 break;
659 }
660 }
661
662 /*
663 * "Old" PCI controller-specific functions.
664 */
665
666 void
667 icp_pci_copy_cmd(struct icp_softc *icp, struct icp_ccb *ccb)
668 {
669
670 /* XXX Not yet implemented */
671 }
672
673 u_int8_t
674 icp_pci_get_status(struct icp_softc *icp)
675 {
676
677 /* XXX Not yet implemented */
678 return (0);
679 }
680
681 void
682 icp_pci_intr(struct icp_softc *icp, struct icp_intr_ctx *ctx)
683 {
684
685 /* XXX Not yet implemented */
686 }
687
688 void
689 icp_pci_release_event(struct icp_softc *icp, struct icp_ccb *ccb)
690 {
691
692 /* XXX Not yet implemented */
693 }
694
695 void
696 icp_pci_set_sema0(struct icp_softc *icp)
697 {
698
699 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_SEMA0, 1);
700 }
701
702 int
703 icp_pci_test_busy(struct icp_softc *icp)
704 {
705
706 /* XXX Not yet implemented */
707 return (0);
708 }
709
710 /*
711 * "New" PCI controller-specific functions.
712 */
713
714 void
715 icp_pcinew_copy_cmd(struct icp_softc *icp, struct icp_ccb *ccb)
716 {
717
718 /* XXX Not yet implemented */
719 }
720
721 u_int8_t
722 icp_pcinew_get_status(struct icp_softc *icp)
723 {
724
725 /* XXX Not yet implemented */
726 return (0);
727 }
728
729 void
730 icp_pcinew_intr(struct icp_softc *icp, struct icp_intr_ctx *ctx)
731 {
732
733 /* XXX Not yet implemented */
734 }
735
736 void
737 icp_pcinew_release_event(struct icp_softc *icp, struct icp_ccb *ccb)
738 {
739
740 /* XXX Not yet implemented */
741 }
742
743 void
744 icp_pcinew_set_sema0(struct icp_softc *icp)
745 {
746
747 bus_space_write_1(icp->icp_iot, icp->icp_ioh, ICP_SEMA0_REG, 1);
748 }
749
750 int
751 icp_pcinew_test_busy(struct icp_softc *icp)
752 {
753
754 /* XXX Not yet implemented */
755 return (0);
756 }
757
758 /*
759 * MPR PCI controller-specific functions
760 */
761
762 void
763 icp_mpr_copy_cmd(struct icp_softc *icp, struct icp_ccb *ic)
764 {
765
766 bus_space_write_2(icp->icp_dpmemt, icp->icp_dpmemh,
767 ICP_MPR_IC + ICP_COMM_QUEUE + 0 * ICP_COMM_Q_SZ + ICP_OFFSET,
768 ICP_DPR_CMD);
769 bus_space_write_2(icp->icp_dpmemt, icp->icp_dpmemh,
770 ICP_MPR_IC + ICP_COMM_QUEUE + 0 * ICP_COMM_Q_SZ + ICP_SERV_ID,
771 ic->ic_service);
772 bus_space_write_region_4(icp->icp_dpmemt, icp->icp_dpmemh,
773 ICP_MPR_IC + ICP_DPR_CMD, (u_int32_t *)&ic->ic_cmd,
774 ic->ic_cmdlen >> 2);
775 }
776
777 u_int8_t
778 icp_mpr_get_status(struct icp_softc *icp)
779 {
780
781 return (bus_space_read_1(icp->icp_dpmemt, icp->icp_dpmemh,
782 ICP_MPR_EDOOR));
783 }
784
785 void
786 icp_mpr_intr(struct icp_softc *icp, struct icp_intr_ctx *ctx)
787 {
788
789 if ((ctx->istatus & 0x80) != 0) { /* error flag */
790 ctx->istatus &= ~0x80;
791 ctx->cmd_status = bus_space_read_2(icp->icp_dpmemt,
792 icp->icp_dpmemh, ICP_MPR_STATUS);
793 } else
794 ctx->cmd_status = ICP_S_OK;
795
796 ctx->service = bus_space_read_2(icp->icp_dpmemt, icp->icp_dpmemh,
797 ICP_MPR_SERVICE);
798 ctx->info = bus_space_read_4(icp->icp_dpmemt, icp->icp_dpmemh,
799 ICP_MPR_INFO);
800 ctx->info2 = bus_space_read_4(icp->icp_dpmemt, icp->icp_dpmemh,
801 ICP_MPR_INFO + sizeof(u_int32_t));
802
803 /*
804 * XXX Read async event string here.
805 */
806
807 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_MPR_EDOOR,
808 0xff);
809 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_MPR_SEMA1, 0);
810 }
811
812 void
813 icp_mpr_release_event(struct icp_softc *icp, struct icp_ccb *ic)
814 {
815
816 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_MPR_LDOOR, 1);
817 }
818
819 void
820 icp_mpr_set_sema0(struct icp_softc *icp)
821 {
822
823 bus_space_write_1(icp->icp_dpmemt, icp->icp_dpmemh, ICP_MPR_SEMA0, 1);
824 }
825
826 int
827 icp_mpr_test_busy(struct icp_softc *icp)
828 {
829
830 return (bus_space_read_1(icp->icp_dpmemt, icp->icp_dpmemh,
831 ICP_MPR_SEMA0) & 1);
832 }
833