1 /*-
2 * PCI specific probe and attach routines for LSI Fusion Adapters
3 * FreeBSD Version.
4 *
5 * SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause
6 *
7 * Copyright (c) 2000, 2001 by Greg Ansley
8 * Partially derived from Matt Jacob's ISP driver.
9 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002 by Matthew Jacob
10 * Feral Software
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice immediately at the beginning of the file, without modification,
18 * this list of conditions, and the following disclaimer.
19 * 2. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34 /*-
35 * Copyright (c) 2002, 2006 by Matthew Jacob
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions are
40 * met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
44 * substantially similar to the "NO WARRANTY" disclaimer below
45 * ("Disclaimer") and any redistribution must be conditioned upon including
46 * a substantially similar Disclaimer requirement for further binary
47 * redistribution.
48 * 3. Neither the names of the above listed copyright holders nor the names
49 * of any contributors may be used to endorse or promote products derived
50 * from this software without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
53 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
56 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
57 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
58 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
59 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
60 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
62 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63 *
64 * Support from Chris Ellsworth in order to make SAS adapters work
65 * is gratefully acknowledged.
66 *
67 * Support from LSI-Logic has also gone a great deal toward making this a
68 * workable subsystem and is gratefully acknowledged.
69 */
70 /*
71 * Copyright (c) 2004, Avid Technology, Inc. and its contributors.
72 * Copyright (c) 2005, WHEEL Sp. z o.o.
73 * Copyright (c) 2004, 2005 Justin T. Gibbs
74 * All rights reserved.
75 *
76 * Redistribution and use in source and binary forms, with or without
77 * modification, are permitted provided that the following conditions are
78 * met:
79 * 1. Redistributions of source code must retain the above copyright
80 * notice, this list of conditions and the following disclaimer.
81 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
82 * substantially similar to the "NO WARRANTY" disclaimer below
83 * ("Disclaimer") and any redistribution must be conditioned upon including
84 * a substantially similar Disclaimer requirement for further binary
85 * redistribution.
86 * 3. Neither the names of the above listed copyright holders nor the names
87 * of any contributors may be used to endorse or promote products derived
88 * from this software without specific prior written permission.
89 *
90 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
91 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
92 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
93 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
94 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
95 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
96 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
97 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
98 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
99 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
100 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
101 */
102
103 #include <sys/cdefs.h>
104 #include <dev/mpt/mpt.h>
105 #include <dev/mpt/mpt_cam.h>
106 #include <dev/mpt/mpt_raid.h>
107
108 /*
109 * XXX it seems no other MPT driver knows about the following chips.
110 */
111
112 #ifndef MPI_MANUFACTPAGE_DEVICEID_FC909_FB
113 #define MPI_MANUFACTPAGE_DEVICEID_FC909_FB 0x0620
114 #endif
115
116 #ifndef MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB
117 #define MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB 0x0625
118 #endif
119
120 #ifndef MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB
121 #define MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB 0x0623
122 #endif
123
124 #ifndef MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB
125 #define MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB 0x0627
126 #endif
127
128 #ifndef MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB
129 #define MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB 0x0629
130 #endif
131
132 #ifndef MPI_MANUFACTPAGE_DEVID_SAS1068A_FB
133 #define MPI_MANUFACTPAGE_DEVID_SAS1068A_FB 0x0055
134 #endif
135
136 #ifndef MPI_MANUFACTPAGE_DEVID_SAS1068E_FB
137 #define MPI_MANUFACTPAGE_DEVID_SAS1068E_FB 0x0059
138 #endif
139
140 #ifndef MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB
141 #define MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB 0x007C
142 #endif
143
144 static int mpt_pci_probe(device_t);
145 static int mpt_pci_attach(device_t);
146 static void mpt_free_bus_resources(struct mpt_softc *mpt);
147 static int mpt_pci_detach(device_t);
148 static int mpt_pci_shutdown(device_t);
149 static int mpt_dma_mem_alloc(struct mpt_softc *mpt);
150 static void mpt_dma_mem_free(struct mpt_softc *mpt);
151 #if 0
152 static void mpt_read_config_regs(struct mpt_softc *mpt);
153 static void mpt_set_config_regs(struct mpt_softc *mpt);
154 #endif
155 static void mpt_pci_intr(void *);
156
157 static device_method_t mpt_methods[] = {
158 /* Device interface */
159 DEVMETHOD(device_probe, mpt_pci_probe),
160 DEVMETHOD(device_attach, mpt_pci_attach),
161 DEVMETHOD(device_detach, mpt_pci_detach),
162 DEVMETHOD(device_shutdown, mpt_pci_shutdown),
163 DEVMETHOD_END
164 };
165
166 static driver_t mpt_driver = {
167 "mpt", mpt_methods, sizeof(struct mpt_softc)
168 };
169
170 DRIVER_MODULE(mpt, pci, mpt_driver, NULL, NULL);
171 MODULE_DEPEND(mpt, pci, 1, 1, 1);
172 MODULE_VERSION(mpt, 1);
173
174 static int
mpt_pci_probe(device_t dev)175 mpt_pci_probe(device_t dev)
176 {
177 const char *desc;
178 int rval;
179
180 if (pci_get_vendor(dev) != MPI_MANUFACTPAGE_VENDORID_LSILOGIC)
181 return (ENXIO);
182
183 rval = BUS_PROBE_DEFAULT;
184 switch (pci_get_device(dev)) {
185 case MPI_MANUFACTPAGE_DEVICEID_FC909_FB:
186 desc = "LSILogic FC909 FC Adapter";
187 break;
188 case MPI_MANUFACTPAGE_DEVICEID_FC909:
189 desc = "LSILogic FC909A FC Adapter";
190 break;
191 case MPI_MANUFACTPAGE_DEVICEID_FC919:
192 desc = "LSILogic FC919 FC Adapter";
193 break;
194 case MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB:
195 desc = "LSILogic FC919 LAN Adapter";
196 break;
197 case MPI_MANUFACTPAGE_DEVICEID_FC929:
198 desc = "Dual LSILogic FC929 FC Adapter";
199 break;
200 case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB:
201 desc = "Dual LSILogic FC929 LAN Adapter";
202 break;
203 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
204 desc = "LSILogic FC919 FC PCI-X Adapter";
205 break;
206 case MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB:
207 desc = "LSILogic FC919 LAN PCI-X Adapter";
208 break;
209 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
210 desc = "Dual LSILogic FC929X 2Gb/s FC PCI-X Adapter";
211 break;
212 case MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB:
213 desc = "Dual LSILogic FC929X LAN PCI-X Adapter";
214 break;
215 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
216 desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-Express Adapter";
217 break;
218 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
219 desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-X Adapter";
220 break;
221 case MPI_MANUFACTPAGE_DEVID_53C1030:
222 case MPI_MANUFACTPAGE_DEVID_53C1030ZC:
223 desc = "LSILogic 1030 Ultra4 Adapter";
224 break;
225 case MPI_MANUFACTPAGE_DEVID_SAS1068E_FB:
226 /*
227 * Allow mfi(4) to claim this device in case it's in MegaRAID
228 * mode.
229 */
230 rval = BUS_PROBE_LOW_PRIORITY;
231 /* FALLTHROUGH */
232 case MPI_MANUFACTPAGE_DEVID_SAS1064:
233 case MPI_MANUFACTPAGE_DEVID_SAS1064A:
234 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
235 case MPI_MANUFACTPAGE_DEVID_SAS1066:
236 case MPI_MANUFACTPAGE_DEVID_SAS1066E:
237 case MPI_MANUFACTPAGE_DEVID_SAS1068:
238 case MPI_MANUFACTPAGE_DEVID_SAS1068A_FB:
239 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
240 case MPI_MANUFACTPAGE_DEVID_SAS1078:
241 case MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB:
242 desc = "LSILogic SAS/SATA Adapter";
243 break;
244 default:
245 return (ENXIO);
246 }
247
248 device_set_desc(dev, desc);
249 return (rval);
250 }
251
252 static void
mpt_set_options(struct mpt_softc * mpt)253 mpt_set_options(struct mpt_softc *mpt)
254 {
255 int tval;
256
257 tval = 0;
258 if (resource_int_value(device_get_name(mpt->dev),
259 device_get_unit(mpt->dev), "debug", &tval) == 0 && tval != 0) {
260 mpt->verbose = tval;
261 }
262 tval = -1;
263 if (resource_int_value(device_get_name(mpt->dev),
264 device_get_unit(mpt->dev), "role", &tval) == 0 && tval >= 0 &&
265 tval <= 3) {
266 mpt->cfg_role = tval;
267 mpt->do_cfg_role = 1;
268 }
269 tval = 0;
270 mpt->msi_enable = 0;
271 if (mpt->is_sas)
272 mpt->msi_enable = 1;
273 if (resource_int_value(device_get_name(mpt->dev),
274 device_get_unit(mpt->dev), "msi_enable", &tval) == 0) {
275 mpt->msi_enable = tval;
276 }
277 }
278
279 #if 0
280 static void
281 mpt_link_peer(struct mpt_softc *mpt)
282 {
283 struct mpt_softc *mpt2;
284
285 if (mpt->unit == 0) {
286 return;
287 }
288 /*
289 * XXX: depends on probe order
290 */
291 mpt2 = devclass_get_softc(device_get_devclass(mpt->dev), mpt->unit - 1);
292
293 if (mpt2 == NULL) {
294 return;
295 }
296 if (pci_get_vendor(mpt2->dev) != pci_get_vendor(mpt->dev)) {
297 return;
298 }
299 if (pci_get_device(mpt2->dev) != pci_get_device(mpt->dev)) {
300 return;
301 }
302 mpt->mpt2 = mpt2;
303 mpt2->mpt2 = mpt;
304 if (mpt->verbose >= MPT_PRT_DEBUG) {
305 mpt_prt(mpt, "linking with peer (mpt%d)\n",
306 device_get_unit(mpt2->dev));
307 }
308 }
309
310 static void
311 mpt_unlink_peer(struct mpt_softc *mpt)
312 {
313
314 if (mpt->mpt2) {
315 mpt->mpt2->mpt2 = NULL;
316 }
317 }
318 #endif
319
320 static int
mpt_pci_attach(device_t dev)321 mpt_pci_attach(device_t dev)
322 {
323 struct mpt_softc *mpt;
324 int iqd;
325 uint32_t val;
326 int mpt_io_bar, mpt_mem_bar;
327
328 mpt = (struct mpt_softc*)device_get_softc(dev);
329
330 switch (pci_get_device(dev)) {
331 case MPI_MANUFACTPAGE_DEVICEID_FC909_FB:
332 case MPI_MANUFACTPAGE_DEVICEID_FC909:
333 case MPI_MANUFACTPAGE_DEVICEID_FC919:
334 case MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB:
335 case MPI_MANUFACTPAGE_DEVICEID_FC929:
336 case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB:
337 case MPI_MANUFACTPAGE_DEVICEID_FC929X:
338 case MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB:
339 case MPI_MANUFACTPAGE_DEVICEID_FC919X:
340 case MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB:
341 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
342 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
343 mpt->is_fc = 1;
344 break;
345 case MPI_MANUFACTPAGE_DEVID_SAS1078:
346 case MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB:
347 mpt->is_1078 = 1;
348 /* FALLTHROUGH */
349 case MPI_MANUFACTPAGE_DEVID_SAS1064:
350 case MPI_MANUFACTPAGE_DEVID_SAS1064A:
351 case MPI_MANUFACTPAGE_DEVID_SAS1064E:
352 case MPI_MANUFACTPAGE_DEVID_SAS1066:
353 case MPI_MANUFACTPAGE_DEVID_SAS1066E:
354 case MPI_MANUFACTPAGE_DEVID_SAS1068:
355 case MPI_MANUFACTPAGE_DEVID_SAS1068A_FB:
356 case MPI_MANUFACTPAGE_DEVID_SAS1068E:
357 case MPI_MANUFACTPAGE_DEVID_SAS1068E_FB:
358 mpt->is_sas = 1;
359 break;
360 default:
361 mpt->is_spi = 1;
362 break;
363 }
364 mpt->dev = dev;
365 mpt->unit = device_get_unit(dev);
366 mpt->raid_resync_rate = MPT_RAID_RESYNC_RATE_DEFAULT;
367 mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT;
368 mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT;
369 mpt->verbose = MPT_PRT_NONE;
370 mpt->role = MPT_ROLE_NONE;
371 mpt->mpt_ini_id = MPT_INI_ID_NONE;
372 mpt_set_options(mpt);
373 if (mpt->verbose == MPT_PRT_NONE) {
374 mpt->verbose = MPT_PRT_WARN;
375 /* Print INFO level (if any) if bootverbose is set */
376 mpt->verbose += (bootverbose != 0)? 1 : 0;
377 }
378
379 /*
380 * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set.
381 */
382 val = pci_read_config(dev, PCIR_COMMAND, 2);
383 val |= PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN |
384 PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
385 pci_write_config(dev, PCIR_COMMAND, val, 2);
386
387 /*
388 * Make sure we've disabled the ROM.
389 */
390 val = pci_read_config(dev, PCIR_BIOS, 4);
391 val &= ~PCIM_BIOS_ENABLE;
392 pci_write_config(dev, PCIR_BIOS, val, 4);
393
394 #if 0
395 /*
396 * Is this part a dual?
397 * If so, link with our partner (around yet)
398 */
399 switch (pci_get_device(dev)) {
400 case MPI_MANUFACTPAGE_DEVICEID_FC929:
401 case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB:
402 case MPI_MANUFACTPAGE_DEVICEID_FC949E:
403 case MPI_MANUFACTPAGE_DEVICEID_FC949X:
404 case MPI_MANUFACTPAGE_DEVID_53C1030:
405 case MPI_MANUFACTPAGE_DEVID_53C1030ZC:
406 mpt_link_peer(mpt);
407 break;
408 default:
409 break;
410 }
411 #endif
412
413 /*
414 * Figure out which are the I/O and MEM Bars
415 */
416 val = pci_read_config(dev, PCIR_BAR(0), 4);
417 if (PCI_BAR_IO(val)) {
418 /* BAR0 is IO, BAR1 is memory */
419 mpt_io_bar = 0;
420 mpt_mem_bar = 1;
421 } else {
422 /* BAR0 is memory, BAR1 is IO */
423 mpt_mem_bar = 0;
424 mpt_io_bar = 1;
425 }
426
427 /*
428 * Set up register access. PIO mode is required for
429 * certain reset operations (but must be disabled for
430 * some cards otherwise).
431 */
432 mpt_io_bar = PCIR_BAR(mpt_io_bar);
433 mpt->pci_pio_reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
434 &mpt_io_bar, RF_ACTIVE);
435 if (mpt->pci_pio_reg == NULL) {
436 if (bootverbose) {
437 device_printf(dev,
438 "unable to map registers in PIO mode\n");
439 }
440 } else {
441 mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg);
442 mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg);
443 }
444
445 mpt_mem_bar = PCIR_BAR(mpt_mem_bar);
446 mpt->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
447 &mpt_mem_bar, RF_ACTIVE);
448 if (mpt->pci_reg == NULL) {
449 if (bootverbose || mpt->is_sas || mpt->pci_pio_reg == NULL) {
450 device_printf(dev,
451 "Unable to memory map registers.\n");
452 }
453 if (mpt->is_sas || mpt->pci_pio_reg == NULL) {
454 device_printf(dev, "Giving Up.\n");
455 goto bad;
456 }
457 if (bootverbose) {
458 device_printf(dev, "Falling back to PIO mode.\n");
459 }
460 mpt->pci_st = mpt->pci_pio_st;
461 mpt->pci_sh = mpt->pci_pio_sh;
462 } else {
463 mpt->pci_st = rman_get_bustag(mpt->pci_reg);
464 mpt->pci_sh = rman_get_bushandle(mpt->pci_reg);
465 }
466
467 /* Get a handle to the interrupt */
468 iqd = 0;
469 if (mpt->msi_enable) {
470 /*
471 * First try to alloc an MSI-X message. If that
472 * fails, then try to alloc an MSI message instead.
473 */
474 val = 1;
475 if (pci_alloc_msix(dev, &val) == 0)
476 iqd = 1;
477 val = 1;
478 if (iqd == 0 && pci_alloc_msi(dev, &val) == 0)
479 iqd = 1;
480 }
481 mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
482 RF_ACTIVE | (iqd != 0 ? 0 : RF_SHAREABLE));
483 if (mpt->pci_irq == NULL) {
484 device_printf(dev, "could not allocate interrupt\n");
485 goto bad;
486 }
487
488 MPT_LOCK_SETUP(mpt);
489
490 /* Disable interrupts at the part */
491 mpt_disable_ints(mpt);
492
493 /* Register the interrupt handler */
494 if (bus_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, NULL, mpt_pci_intr,
495 mpt, &mpt->ih)) {
496 device_printf(dev, "could not setup interrupt\n");
497 goto bad;
498 }
499
500 /* Allocate dma memory */
501 if (mpt_dma_mem_alloc(mpt)) {
502 mpt_prt(mpt, "Could not allocate DMA memory\n");
503 goto bad;
504 }
505
506 #if 0
507 /*
508 * Save the PCI config register values
509 *
510 * Hard resets are known to screw up the BAR for diagnostic
511 * memory accesses (Mem1).
512 *
513 * Using Mem1 is known to make the chip stop responding to
514 * configuration space transfers, so we need to save it now
515 */
516
517 mpt_read_config_regs(mpt);
518 #endif
519
520 /*
521 * Disable PIO until we need it
522 */
523 if (mpt->is_sas) {
524 pci_disable_io(dev, SYS_RES_IOPORT);
525 }
526
527 /* Initialize the hardware */
528 if (mpt->disabled == 0) {
529 if (mpt_attach(mpt) != 0) {
530 goto bad;
531 }
532 } else {
533 mpt_prt(mpt, "device disabled at user request\n");
534 goto bad;
535 }
536
537 mpt->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, mpt_pci_shutdown,
538 dev, SHUTDOWN_PRI_LAST);
539
540 if (mpt->eh == NULL) {
541 mpt_prt(mpt, "shutdown event registration failed\n");
542 mpt_disable_ints(mpt);
543 (void) mpt_detach(mpt);
544 mpt_reset(mpt, /*reinit*/FALSE);
545 mpt_raid_free_mem(mpt);
546 goto bad;
547 }
548 return (0);
549
550 bad:
551 mpt_dma_mem_free(mpt);
552 mpt_free_bus_resources(mpt);
553 #if 0
554 mpt_unlink_peer(mpt);
555 #endif
556
557 MPT_LOCK_DESTROY(mpt);
558
559 /*
560 * but return zero to preserve unit numbering
561 */
562 return (0);
563 }
564
565 /*
566 * Free bus resources
567 */
568 static void
mpt_free_bus_resources(struct mpt_softc * mpt)569 mpt_free_bus_resources(struct mpt_softc *mpt)
570 {
571
572 if (mpt->ih) {
573 bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih);
574 mpt->ih = NULL;
575 }
576
577 if (mpt->pci_irq) {
578 bus_release_resource(mpt->dev, SYS_RES_IRQ,
579 rman_get_rid(mpt->pci_irq), mpt->pci_irq);
580 pci_release_msi(mpt->dev);
581 mpt->pci_irq = NULL;
582 }
583
584 if (mpt->pci_pio_reg) {
585 bus_release_resource(mpt->dev, SYS_RES_IOPORT,
586 rman_get_rid(mpt->pci_pio_reg), mpt->pci_pio_reg);
587 mpt->pci_pio_reg = NULL;
588 }
589
590 if (mpt->pci_reg) {
591 bus_release_resource(mpt->dev, SYS_RES_MEMORY,
592 rman_get_rid(mpt->pci_reg), mpt->pci_reg);
593 mpt->pci_reg = NULL;
594 }
595 }
596
597 /*
598 * Disconnect ourselves from the system.
599 */
600 static int
mpt_pci_detach(device_t dev)601 mpt_pci_detach(device_t dev)
602 {
603 struct mpt_softc *mpt;
604
605 mpt = (struct mpt_softc*)device_get_softc(dev);
606
607 if (mpt) {
608 mpt_disable_ints(mpt);
609 mpt_detach(mpt);
610 mpt_reset(mpt, /*reinit*/FALSE);
611 mpt_raid_free_mem(mpt);
612 mpt_dma_mem_free(mpt);
613 mpt_free_bus_resources(mpt);
614 #if 0
615 mpt_unlink_peer(mpt);
616 #endif
617 if (mpt->eh != NULL) {
618 EVENTHANDLER_DEREGISTER(shutdown_post_sync, mpt->eh);
619 }
620 MPT_LOCK_DESTROY(mpt);
621 }
622 return(0);
623 }
624
625 /*
626 * Disable the hardware
627 */
628 static int
mpt_pci_shutdown(device_t dev)629 mpt_pci_shutdown(device_t dev)
630 {
631 struct mpt_softc *mpt;
632
633 mpt = (struct mpt_softc *)device_get_softc(dev);
634 if (mpt)
635 return (mpt_shutdown(mpt));
636 return(0);
637 }
638
639 static int
mpt_dma_mem_alloc(struct mpt_softc * mpt)640 mpt_dma_mem_alloc(struct mpt_softc *mpt)
641 {
642 size_t len;
643 struct mpt_map_info mi;
644
645 /* Check if we alreay have allocated the reply memory */
646 if (mpt->reply_phys != 0) {
647 return 0;
648 }
649
650 len = sizeof (request_t) * MPT_MAX_REQUESTS(mpt);
651 mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK|M_ZERO);
652
653 /*
654 * Create a parent dma tag for this device.
655 *
656 * Align at byte boundaries,
657 * Limit to 32-bit addressing for request/reply queues.
658 */
659 if (mpt_dma_tag_create(mpt, /*parent*/bus_get_dma_tag(mpt->dev),
660 /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR,
661 /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL,
662 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
663 /*nsegments*/BUS_SPACE_UNRESTRICTED,
664 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0,
665 &mpt->parent_dmat) != 0) {
666 mpt_prt(mpt, "cannot create parent dma tag\n");
667 return (1);
668 }
669
670 /* Create a child tag for reply buffers */
671 if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0,
672 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
673 NULL, NULL, 2 * PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0,
674 &mpt->reply_dmat) != 0) {
675 mpt_prt(mpt, "cannot create a dma tag for replies\n");
676 return (1);
677 }
678
679 /* Allocate some DMA accessible memory for replies */
680 if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply,
681 BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) {
682 mpt_prt(mpt, "cannot allocate %lu bytes of reply memory\n",
683 (u_long) (2 * PAGE_SIZE));
684 return (1);
685 }
686
687 mi.mpt = mpt;
688 mi.error = 0;
689
690 /* Load and lock it into "bus space" */
691 bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply,
692 2 * PAGE_SIZE, mpt_map_rquest, &mi, 0);
693
694 if (mi.error) {
695 mpt_prt(mpt, "error %d loading dma map for DMA reply queue\n",
696 mi.error);
697 return (1);
698 }
699 mpt->reply_phys = mi.phys;
700
701 return (0);
702 }
703
704 /* Deallocate memory that was allocated by mpt_dma_mem_alloc
705 */
706 static void
mpt_dma_mem_free(struct mpt_softc * mpt)707 mpt_dma_mem_free(struct mpt_softc *mpt)
708 {
709
710 /* Make sure we aren't double destroying */
711 if (mpt->reply_dmat == 0) {
712 mpt_lprt(mpt, MPT_PRT_DEBUG, "already released dma memory\n");
713 return;
714 }
715
716 bus_dmamap_unload(mpt->reply_dmat, mpt->reply_dmap);
717 bus_dmamem_free(mpt->reply_dmat, mpt->reply, mpt->reply_dmap);
718 bus_dma_tag_destroy(mpt->reply_dmat);
719 bus_dma_tag_destroy(mpt->parent_dmat);
720 mpt->reply_dmat = NULL;
721 free(mpt->request_pool, M_DEVBUF);
722 mpt->request_pool = NULL;
723 }
724
725 #if 0
726 /* Reads modifiable (via PCI transactions) config registers */
727 static void
728 mpt_read_config_regs(struct mpt_softc *mpt)
729 {
730
731 mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2);
732 mpt->pci_cfg.LatencyTimer_LineSize =
733 pci_read_config(mpt->dev, PCIR_CACHELNSZ, 2);
734 mpt->pci_cfg.IO_BAR = pci_read_config(mpt->dev, PCIR_BAR(0), 4);
735 mpt->pci_cfg.Mem0_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(1), 4);
736 mpt->pci_cfg.Mem0_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(2), 4);
737 mpt->pci_cfg.Mem1_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(3), 4);
738 mpt->pci_cfg.Mem1_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(4), 4);
739 mpt->pci_cfg.ROM_BAR = pci_read_config(mpt->dev, PCIR_BIOS, 4);
740 mpt->pci_cfg.IntLine = pci_read_config(mpt->dev, PCIR_INTLINE, 1);
741 mpt->pci_cfg.PMCSR = pci_read_config(mpt->dev, 0x44, 4);
742 }
743
744 /* Sets modifiable config registers */
745 static void
746 mpt_set_config_regs(struct mpt_softc *mpt)
747 {
748 uint32_t val;
749
750 #define MPT_CHECK(reg, offset, size) \
751 val = pci_read_config(mpt->dev, offset, size); \
752 if (mpt->pci_cfg.reg != val) { \
753 mpt_prt(mpt, \
754 "Restoring " #reg " to 0x%X from 0x%X\n", \
755 mpt->pci_cfg.reg, val); \
756 }
757
758 if (mpt->verbose >= MPT_PRT_DEBUG) {
759 MPT_CHECK(Command, PCIR_COMMAND, 2);
760 MPT_CHECK(LatencyTimer_LineSize, PCIR_CACHELNSZ, 2);
761 MPT_CHECK(IO_BAR, PCIR_BAR(0), 4);
762 MPT_CHECK(Mem0_BAR[0], PCIR_BAR(1), 4);
763 MPT_CHECK(Mem0_BAR[1], PCIR_BAR(2), 4);
764 MPT_CHECK(Mem1_BAR[0], PCIR_BAR(3), 4);
765 MPT_CHECK(Mem1_BAR[1], PCIR_BAR(4), 4);
766 MPT_CHECK(ROM_BAR, PCIR_BIOS, 4);
767 MPT_CHECK(IntLine, PCIR_INTLINE, 1);
768 MPT_CHECK(PMCSR, 0x44, 4);
769 }
770 #undef MPT_CHECK
771
772 pci_write_config(mpt->dev, PCIR_COMMAND, mpt->pci_cfg.Command, 2);
773 pci_write_config(mpt->dev, PCIR_CACHELNSZ,
774 mpt->pci_cfg.LatencyTimer_LineSize, 2);
775 pci_write_config(mpt->dev, PCIR_BAR(0), mpt->pci_cfg.IO_BAR, 4);
776 pci_write_config(mpt->dev, PCIR_BAR(1), mpt->pci_cfg.Mem0_BAR[0], 4);
777 pci_write_config(mpt->dev, PCIR_BAR(2), mpt->pci_cfg.Mem0_BAR[1], 4);
778 pci_write_config(mpt->dev, PCIR_BAR(3), mpt->pci_cfg.Mem1_BAR[0], 4);
779 pci_write_config(mpt->dev, PCIR_BAR(4), mpt->pci_cfg.Mem1_BAR[1], 4);
780 pci_write_config(mpt->dev, PCIR_BIOS, mpt->pci_cfg.ROM_BAR, 4);
781 pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1);
782 pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4);
783 }
784 #endif
785
786 static void
mpt_pci_intr(void * arg)787 mpt_pci_intr(void *arg)
788 {
789 struct mpt_softc *mpt;
790
791 mpt = (struct mpt_softc *)arg;
792 MPT_LOCK(mpt);
793 mpt_intr(mpt);
794 MPT_UNLOCK(mpt);
795 }
796