Bring in mps(4) for LSI Fusion-MPT 2 Serial Attached SCSI controllers.
[dragonfly.git] / sys / dev / disk / mps / mps.c
1 /*-
2  * Copyright (c) 2009 Yahoo! Inc.
3  * All rights reserved.
4  *
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
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.
13  *
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
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/dev/mps/mps.c,v 1.9 2010/12/10 21:45:10 ken Exp $
27  */
28
29 /* Communications core for LSI MPT2 */
30
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/lock.h>
36 #include <sys/mutex.h>
37 #include <sys/module.h>
38 #include <sys/bus.h>
39 #include <sys/conf.h>
40 #include <sys/bio.h>
41 #include <sys/malloc.h>
42 #include <sys/uio.h>
43 #include <sys/sysctl.h>
44 #include <sys/endian.h>
45
46 #include <sys/rman.h>
47
48 #include <bus/cam/scsi/scsi_all.h>
49
50 #include <dev/disk/mps/mpi/mpi2_type.h>
51 #include <dev/disk/mps/mpi/mpi2.h>
52 #include <dev/disk/mps/mpi/mpi2_ioc.h>
53 #include <dev/disk/mps/mpi/mpi2_cnfg.h>
54 #include <dev/disk/mps/mpsvar.h>
55 #include <dev/disk/mps/mps_table.h>
56
57 static void mps_startup(void *arg);
58 static void mps_startup_complete(struct mps_softc *sc, struct mps_command *cm);
59 static int mps_send_iocinit(struct mps_softc *sc);
60 static int mps_attach_log(struct mps_softc *sc);
61 static void mps_dispatch_event(struct mps_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *reply);
62 static void mps_config_complete(struct mps_softc *sc, struct mps_command *cm);
63 static void mps_periodic(void *);
64
65 SYSCTL_NODE(_hw, OID_AUTO, mps, CTLFLAG_RD, 0, "MPS Driver Parameters");
66
67 MALLOC_DEFINE(M_MPT2, "mps", "mpt2 driver memory");
68
69 /*
70  * Do a "Diagnostic Reset" aka a hard reset.  This should get the chip out of
71  * any state and back to its initialization state machine.
72  */
73 static char mpt2_reset_magic[] = { 0x00, 0x0f, 0x04, 0x0b, 0x02, 0x07, 0x0d };
74
75 static int
76 mps_hard_reset(struct mps_softc *sc)
77 {
78         uint32_t reg;
79         int i, error, tries = 0;
80
81         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
82
83         /* Clear any pending interrupts */
84         mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
85
86         /* Push the magic sequence */
87         error = ETIMEDOUT;
88         while (tries++ < 20) {
89                 for (i = 0; i < sizeof(mpt2_reset_magic); i++)
90                         mps_regwrite(sc, MPI2_WRITE_SEQUENCE_OFFSET,
91                             mpt2_reset_magic[i]);
92
93                 DELAY(100 * 1000);
94
95                 reg = mps_regread(sc, MPI2_HOST_DIAGNOSTIC_OFFSET);
96                 if (reg & MPI2_DIAG_DIAG_WRITE_ENABLE) {
97                         error = 0;
98                         break;
99                 }
100         }
101         if (error)
102                 return (error);
103
104         /* Send the actual reset.  XXX need to refresh the reg? */
105         mps_regwrite(sc, MPI2_HOST_DIAGNOSTIC_OFFSET,
106             reg | MPI2_DIAG_RESET_ADAPTER);
107
108         /* Wait up to 300 seconds in 50ms intervals */
109         error = ETIMEDOUT;
110         for (i = 0; i < 60000; i++) {
111                 DELAY(50000);
112                 reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
113                 if ((reg & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_RESET) {
114                         error = 0;
115                         break;
116                 }
117         }
118         if (error)
119                 return (error);
120
121         mps_regwrite(sc, MPI2_WRITE_SEQUENCE_OFFSET, 0x0);
122
123         return (0);
124 }
125
126 static int
127 mps_soft_reset(struct mps_softc *sc)
128 {
129
130         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
131
132         mps_regwrite(sc, MPI2_DOORBELL_OFFSET,
133             MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET <<
134             MPI2_DOORBELL_FUNCTION_SHIFT);
135         DELAY(50000);
136
137         return (0);
138 }
139
140 static int
141 mps_transition_ready(struct mps_softc *sc)
142 {
143         uint32_t reg, state;
144         int error, tries = 0;
145
146         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
147
148         error = 0;
149         while (tries++ < 5) {
150                 reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
151                 mps_dprint(sc, MPS_INFO, "Doorbell= 0x%x\n", reg);
152
153                 /*
154                  * Ensure the IOC is ready to talk.  If it's not, try
155                  * resetting it.
156                  */
157                 if (reg & MPI2_DOORBELL_USED) {
158                         mps_hard_reset(sc);
159                         DELAY(50000);
160                         continue;
161                 }
162
163                 /* Is the adapter owned by another peer? */
164                 if ((reg & MPI2_DOORBELL_WHO_INIT_MASK) ==
165                     (MPI2_WHOINIT_PCI_PEER << MPI2_DOORBELL_WHO_INIT_SHIFT)) {
166                         device_printf(sc->mps_dev, "IOC is under the control "
167                             "of another peer host, aborting initialization.\n");
168                         return (ENXIO);
169                 }
170
171                 state = reg & MPI2_IOC_STATE_MASK;
172                 if (state == MPI2_IOC_STATE_READY) {
173                         /* Ready to go! */
174                         error = 0;
175                         break;
176                 } else if (state == MPI2_IOC_STATE_FAULT) {
177                         mps_dprint(sc, MPS_INFO, "IOC in fault state 0x%x\n",
178                             state & MPI2_DOORBELL_FAULT_CODE_MASK);
179                         mps_hard_reset(sc);
180                 } else if (state == MPI2_IOC_STATE_OPERATIONAL) {
181                         /* Need to take ownership */
182                         mps_soft_reset(sc);
183                 } else if (state == MPI2_IOC_STATE_RESET) {
184                         /* Wait a bit, IOC might be in transition */
185                         mps_dprint(sc, MPS_FAULT,
186                             "IOC in unexpected reset state\n");
187                 } else {
188                         mps_dprint(sc, MPS_FAULT,
189                             "IOC in unknown state 0x%x\n", state);
190                         error = EINVAL;
191                         break;
192                 }
193
194                 /* Wait 50ms for things to settle down. */
195                 DELAY(50000);
196         }
197
198         if (error)
199                 device_printf(sc->mps_dev, "Cannot transition IOC to ready\n");
200
201         return (error);
202 }
203
204 static int
205 mps_transition_operational(struct mps_softc *sc)
206 {
207         uint32_t reg, state;
208         int error;
209
210         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
211
212         error = 0;
213         reg = mps_regread(sc, MPI2_DOORBELL_OFFSET);
214         mps_dprint(sc, MPS_INFO, "Doorbell= 0x%x\n", reg);
215
216         state = reg & MPI2_IOC_STATE_MASK;
217         if (state != MPI2_IOC_STATE_READY) {
218                 if ((error = mps_transition_ready(sc)) != 0)
219                         return (error);
220         }
221
222         error = mps_send_iocinit(sc);
223         return (error);
224 }
225
226 /* Wait for the chip to ACK a word that we've put into its FIFO */
227 static int
228 mps_wait_db_ack(struct mps_softc *sc)
229 {
230         int retry;
231
232         for (retry = 0; retry < MPS_DB_MAX_WAIT; retry++) {
233                 if ((mps_regread(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET) &
234                     MPI2_HIS_SYS2IOC_DB_STATUS) == 0)
235                         return (0);
236                 DELAY(2000);
237         }
238         return (ETIMEDOUT);
239 }
240
241 /* Wait for the chip to signal that the next word in its FIFO can be fetched */
242 static int
243 mps_wait_db_int(struct mps_softc *sc)
244 {
245         int retry;
246
247         for (retry = 0; retry < MPS_DB_MAX_WAIT; retry++) {
248                 if ((mps_regread(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET) &
249                     MPI2_HIS_IOC2SYS_DB_STATUS) != 0)
250                         return (0);
251                 DELAY(2000);
252         }
253         return (ETIMEDOUT);
254 }
255
256 /* Step through the synchronous command state machine, i.e. "Doorbell mode" */
257 static int
258 mps_request_sync(struct mps_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply,
259     int req_sz, int reply_sz, int timeout)
260 {
261         uint32_t *data32;
262         uint16_t *data16;
263         int i, count, ioc_sz, residual;
264
265         /* Step 1 */
266         mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
267
268         /* Step 2 */
269         if (mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_USED)
270                 return (EBUSY);
271
272         /* Step 3
273          * Announce that a message is coming through the doorbell.  Messages
274          * are pushed at 32bit words, so round up if needed.
275          */
276         count = (req_sz + 3) / 4;
277         mps_regwrite(sc, MPI2_DOORBELL_OFFSET,
278             (MPI2_FUNCTION_HANDSHAKE << MPI2_DOORBELL_FUNCTION_SHIFT) |
279             (count << MPI2_DOORBELL_ADD_DWORDS_SHIFT));
280
281         /* Step 4 */
282         if (mps_wait_db_int(sc) ||
283             (mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_USED) == 0) {
284                 mps_dprint(sc, MPS_FAULT, "Doorbell failed to activate\n");
285                 return (ENXIO);
286         }
287         mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
288         if (mps_wait_db_ack(sc) != 0) {
289                 mps_dprint(sc, MPS_FAULT, "Doorbell handshake failed\n");
290                 return (ENXIO);
291         }
292
293         /* Step 5 */
294         /* Clock out the message data synchronously in 32-bit dwords*/
295         data32 = (uint32_t *)req;
296         for (i = 0; i < count; i++) {
297                 mps_regwrite(sc, MPI2_DOORBELL_OFFSET, data32[i]);
298                 if (mps_wait_db_ack(sc) != 0) {
299                         mps_dprint(sc, MPS_FAULT,
300                             "Timeout while writing doorbell\n");
301                         return (ENXIO);
302                 }
303         }
304
305         /* Step 6 */
306         /* Clock in the reply in 16-bit words.  The total length of the
307          * message is always in the 4th byte, so clock out the first 2 words
308          * manually, then loop the rest.
309          */
310         data16 = (uint16_t *)reply;
311         if (mps_wait_db_int(sc) != 0) {
312                 mps_dprint(sc, MPS_FAULT, "Timeout reading doorbell 0\n");
313                 return (ENXIO);
314         }
315         data16[0] =
316             mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_DATA_MASK;
317         mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
318         if (mps_wait_db_int(sc) != 0) {
319                 mps_dprint(sc, MPS_FAULT, "Timeout reading doorbell 1\n");
320                 return (ENXIO);
321         }
322         data16[1] =
323             mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_DATA_MASK;
324         mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
325
326         /* Number of 32bit words in the message */
327         ioc_sz = reply->MsgLength;
328
329         /*
330          * Figure out how many 16bit words to clock in without overrunning.
331          * The precision loss with dividing reply_sz can safely be
332          * ignored because the messages can only be multiples of 32bits.
333          */
334         residual = 0;
335         count = MIN((reply_sz / 4), ioc_sz) * 2;
336         if (count < ioc_sz * 2) {
337                 residual = ioc_sz * 2 - count;
338                 mps_dprint(sc, MPS_FAULT, "Driver error, throwing away %d "
339                     "residual message words\n", residual);
340         }
341
342         for (i = 2; i < count; i++) {
343                 if (mps_wait_db_int(sc) != 0) {
344                         mps_dprint(sc, MPS_FAULT,
345                             "Timeout reading doorbell %d\n", i);
346                         return (ENXIO);
347                 }
348                 data16[i] = mps_regread(sc, MPI2_DOORBELL_OFFSET) &
349                     MPI2_DOORBELL_DATA_MASK;
350                 mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
351         }
352
353         /*
354          * Pull out residual words that won't fit into the provided buffer.
355          * This keeps the chip from hanging due to a driver programming
356          * error.
357          */
358         while (residual--) {
359                 if (mps_wait_db_int(sc) != 0) {
360                         mps_dprint(sc, MPS_FAULT,
361                             "Timeout reading doorbell\n");
362                         return (ENXIO);
363                 }
364                 (void)mps_regread(sc, MPI2_DOORBELL_OFFSET);
365                 mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
366         }
367
368         /* Step 7 */
369         if (mps_wait_db_int(sc) != 0) {
370                 mps_dprint(sc, MPS_FAULT, "Timeout waiting to exit doorbell\n");
371                 return (ENXIO);
372         }
373         if (mps_regread(sc, MPI2_DOORBELL_OFFSET) & MPI2_DOORBELL_USED)
374                 mps_dprint(sc, MPS_FAULT, "Warning, doorbell still active\n");
375         mps_regwrite(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET, 0x0);
376
377         return (0);
378 }
379
380 void
381 mps_enqueue_request(struct mps_softc *sc, struct mps_command *cm)
382 {
383
384         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
385
386         mps_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET,
387             cm->cm_desc.Words.Low);
388         mps_regwrite(sc, MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET,
389             cm->cm_desc.Words.High);
390 }
391
392 int
393 mps_request_polled(struct mps_softc *sc, struct mps_command *cm)
394 {
395         int error, timeout = 0;
396
397         error = 0;
398
399         cm->cm_flags |= MPS_CM_FLAGS_POLLED;
400         cm->cm_complete = NULL;
401         mps_map_command(sc, cm);
402
403         while ((cm->cm_flags & MPS_CM_FLAGS_COMPLETE) == 0) {
404                 mps_intr(sc);
405                 DELAY(50 * 1000);
406                 if (timeout++ > 1000) {
407                         mps_dprint(sc, MPS_FAULT, "polling failed\n");
408                         error = ETIMEDOUT;
409                         break;
410                 }
411         }
412
413         return (error);
414 }
415
416 /*
417  * Just the FACTS, ma'am.
418  */
419 static int
420 mps_get_iocfacts(struct mps_softc *sc, MPI2_IOC_FACTS_REPLY *facts)
421 {
422         MPI2_DEFAULT_REPLY *reply;
423         MPI2_IOC_FACTS_REQUEST request;
424         int error, req_sz, reply_sz;
425
426         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
427
428         req_sz = sizeof(MPI2_IOC_FACTS_REQUEST);
429         reply_sz = sizeof(MPI2_IOC_FACTS_REPLY);
430         reply = (MPI2_DEFAULT_REPLY *)facts;
431
432         bzero(&request, req_sz);
433         request.Function = MPI2_FUNCTION_IOC_FACTS;
434         error = mps_request_sync(sc, &request, reply, req_sz, reply_sz, 5);
435
436         return (error);
437 }
438
439 static int
440 mps_get_portfacts(struct mps_softc *sc, MPI2_PORT_FACTS_REPLY *facts, int port)
441 {
442         MPI2_PORT_FACTS_REQUEST *request;
443         MPI2_PORT_FACTS_REPLY *reply;
444         struct mps_command *cm;
445         int error;
446
447         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
448
449         if ((cm = mps_alloc_command(sc)) == NULL)
450                 return (EBUSY);
451         request = (MPI2_PORT_FACTS_REQUEST *)cm->cm_req;
452         request->Function = MPI2_FUNCTION_PORT_FACTS;
453         request->PortNumber = port;
454         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
455         cm->cm_data = NULL;
456         error = mps_request_polled(sc, cm);
457         reply = (MPI2_PORT_FACTS_REPLY *)cm->cm_reply;
458         if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
459                 error = ENXIO;
460         bcopy(reply, facts, sizeof(MPI2_PORT_FACTS_REPLY));
461         mps_free_command(sc, cm);
462
463         return (error);
464 }
465
466 static int
467 mps_send_iocinit(struct mps_softc *sc)
468 {
469         MPI2_IOC_INIT_REQUEST   init;
470         MPI2_DEFAULT_REPLY      reply;
471         int req_sz, reply_sz, error;
472
473         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
474
475         req_sz = sizeof(MPI2_IOC_INIT_REQUEST);
476         reply_sz = sizeof(MPI2_IOC_INIT_REPLY);
477         bzero(&init, req_sz);
478         bzero(&reply, reply_sz);
479
480         /*
481          * Fill in the init block.  Note that most addresses are
482          * deliberately in the lower 32bits of memory.  This is a micro-
483          * optimzation for PCI/PCIX, though it's not clear if it helps PCIe.
484          */
485         init.Function = MPI2_FUNCTION_IOC_INIT;
486         init.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
487         init.MsgVersion = MPI2_VERSION;
488         init.HeaderVersion = MPI2_HEADER_VERSION;
489         init.SystemRequestFrameSize = sc->facts->IOCRequestFrameSize;
490         init.ReplyDescriptorPostQueueDepth = sc->pqdepth;
491         init.ReplyFreeQueueDepth = sc->fqdepth;
492         init.SenseBufferAddressHigh = 0;
493         init.SystemReplyAddressHigh = 0;
494         init.SystemRequestFrameBaseAddress.High = 0;
495         init.SystemRequestFrameBaseAddress.Low = (uint32_t)sc->req_busaddr;
496         init.ReplyDescriptorPostQueueAddress.High = 0;
497         init.ReplyDescriptorPostQueueAddress.Low = (uint32_t)sc->post_busaddr;
498         init.ReplyFreeQueueAddress.High = 0;
499         init.ReplyFreeQueueAddress.Low = (uint32_t)sc->free_busaddr;
500         init.TimeStamp.High = 0;
501         init.TimeStamp.Low = (uint32_t)time_second;
502
503         error = mps_request_sync(sc, &init, &reply, req_sz, reply_sz, 5);
504         if ((reply.IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
505                 error = ENXIO;
506
507         mps_dprint(sc, MPS_INFO, "IOCInit status= 0x%x\n", reply.IOCStatus);
508         return (error);
509 }
510
511 static int
512 mps_send_portenable(struct mps_softc *sc)
513 {
514         MPI2_PORT_ENABLE_REQUEST *request;
515         struct mps_command *cm;
516
517         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
518
519         if ((cm = mps_alloc_command(sc)) == NULL)
520                 return (EBUSY);
521         request = (MPI2_PORT_ENABLE_REQUEST *)cm->cm_req;
522         request->Function = MPI2_FUNCTION_PORT_ENABLE;
523         request->MsgFlags = 0;
524         request->VP_ID = 0;
525         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
526         cm->cm_complete = mps_startup_complete;
527
528         mps_enqueue_request(sc, cm);
529         return (0);
530 }
531
532 static int
533 mps_send_mur(struct mps_softc *sc)
534 {
535
536         /* Placeholder */
537         return (0);
538 }
539
540 void
541 mps_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
542 {
543         bus_addr_t *addr;
544
545         addr = arg;
546         *addr = segs[0].ds_addr;
547 }
548
549 static int
550 mps_alloc_queues(struct mps_softc *sc)
551 {
552         bus_addr_t queues_busaddr;
553         uint8_t *queues;
554         int qsize, fqsize, pqsize;
555
556         /*
557          * The reply free queue contains 4 byte entries in multiples of 16 and
558          * aligned on a 16 byte boundary. There must always be an unused entry.
559          * This queue supplies fresh reply frames for the firmware to use.
560          *
561          * The reply descriptor post queue contains 8 byte entries in
562          * multiples of 16 and aligned on a 16 byte boundary.  This queue
563          * contains filled-in reply frames sent from the firmware to the host.
564          *
565          * These two queues are allocated together for simplicity.
566          */
567         sc->fqdepth = roundup2((sc->num_replies + 1), 16);
568         sc->pqdepth = roundup2((sc->num_replies + 1), 16);
569         fqsize= sc->fqdepth * 4;
570         pqsize = sc->pqdepth * 8;
571         qsize = fqsize + pqsize;
572
573         if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
574                                 16, 0,                  /* algnmnt, boundary */
575                                 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
576                                 BUS_SPACE_MAXADDR,      /* highaddr */
577                                 NULL, NULL,             /* filter, filterarg */
578                                 qsize,                  /* maxsize */
579                                 1,                      /* nsegments */
580                                 qsize,                  /* maxsegsize */
581                                 0,                      /* flags */
582                                 &sc->queues_dmat)) {
583                 device_printf(sc->mps_dev, "Cannot allocate queues DMA tag\n");
584                 return (ENOMEM);
585         }
586         if (bus_dmamem_alloc(sc->queues_dmat, (void **)&queues, BUS_DMA_NOWAIT,
587             &sc->queues_map)) {
588                 device_printf(sc->mps_dev, "Cannot allocate queues memory\n");
589                 return (ENOMEM);
590         }
591         bzero(queues, qsize);
592         bus_dmamap_load(sc->queues_dmat, sc->queues_map, queues, qsize,
593             mps_memaddr_cb, &queues_busaddr, 0);
594
595         sc->free_queue = (uint32_t *)queues;
596         sc->free_busaddr = queues_busaddr;
597         sc->post_queue = (MPI2_REPLY_DESCRIPTORS_UNION *)(queues + fqsize);
598         sc->post_busaddr = queues_busaddr + fqsize;
599
600         return (0);
601 }
602
603 static int
604 mps_alloc_replies(struct mps_softc *sc)
605 {
606         int rsize, num_replies;
607
608         /*
609          * sc->num_replies should be one less than sc->fqdepth.  We need to
610          * allocate space for sc->fqdepth replies, but only sc->num_replies
611          * replies can be used at once.
612          */
613         num_replies = max(sc->fqdepth, sc->num_replies);
614
615         rsize = sc->facts->ReplyFrameSize * num_replies * 4;
616         if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
617                                 4, 0,                   /* algnmnt, boundary */
618                                 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
619                                 BUS_SPACE_MAXADDR,      /* highaddr */
620                                 NULL, NULL,             /* filter, filterarg */
621                                 rsize,                  /* maxsize */
622                                 1,                      /* nsegments */
623                                 rsize,                  /* maxsegsize */
624                                 0,                      /* flags */
625                                 &sc->reply_dmat)) {
626                 device_printf(sc->mps_dev, "Cannot allocate replies DMA tag\n");
627                 return (ENOMEM);
628         }
629         if (bus_dmamem_alloc(sc->reply_dmat, (void **)&sc->reply_frames,
630             BUS_DMA_NOWAIT, &sc->reply_map)) {
631                 device_printf(sc->mps_dev, "Cannot allocate replies memory\n");
632                 return (ENOMEM);
633         }
634         bzero(sc->reply_frames, rsize);
635         bus_dmamap_load(sc->reply_dmat, sc->reply_map, sc->reply_frames, rsize,
636             mps_memaddr_cb, &sc->reply_busaddr, 0);
637
638         return (0);
639 }
640
641 static int
642 mps_alloc_requests(struct mps_softc *sc)
643 {
644         struct mps_command *cm;
645         struct mps_chain *chain;
646         int i, rsize, nsegs;
647
648         rsize = sc->facts->IOCRequestFrameSize * sc->num_reqs * 4;
649         if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
650                                 16, 0,                  /* algnmnt, boundary */
651                                 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
652                                 BUS_SPACE_MAXADDR,      /* highaddr */
653                                 NULL, NULL,             /* filter, filterarg */
654                                 rsize,                  /* maxsize */
655                                 1,                      /* nsegments */
656                                 rsize,                  /* maxsegsize */
657                                 0,                      /* flags */
658                                 &sc->req_dmat)) {
659                 device_printf(sc->mps_dev, "Cannot allocate request DMA tag\n");
660                 return (ENOMEM);
661         }
662         if (bus_dmamem_alloc(sc->req_dmat, (void **)&sc->req_frames,
663             BUS_DMA_NOWAIT, &sc->req_map)) {
664                 device_printf(sc->mps_dev, "Cannot allocate request memory\n");
665                 return (ENOMEM);
666         }
667         bzero(sc->req_frames, rsize);
668         bus_dmamap_load(sc->req_dmat, sc->req_map, sc->req_frames, rsize,
669             mps_memaddr_cb, &sc->req_busaddr, 0);
670
671         rsize = sc->facts->IOCRequestFrameSize * MPS_CHAIN_FRAMES * 4;
672         if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
673                                 16, 0,                  /* algnmnt, boundary */
674                                 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
675                                 BUS_SPACE_MAXADDR,      /* highaddr */
676                                 NULL, NULL,             /* filter, filterarg */
677                                 rsize,                  /* maxsize */
678                                 1,                      /* nsegments */
679                                 rsize,                  /* maxsegsize */
680                                 0,                      /* flags */
681                                 &sc->chain_dmat)) {
682                 device_printf(sc->mps_dev, "Cannot allocate chain DMA tag\n");
683                 return (ENOMEM);
684         }
685         if (bus_dmamem_alloc(sc->chain_dmat, (void **)&sc->chain_frames,
686             BUS_DMA_NOWAIT, &sc->chain_map)) {
687                 device_printf(sc->mps_dev, "Cannot allocate chain memory\n");
688                 return (ENOMEM);
689         }
690         bzero(sc->chain_frames, rsize);
691         bus_dmamap_load(sc->chain_dmat, sc->chain_map, sc->chain_frames, rsize,
692             mps_memaddr_cb, &sc->chain_busaddr, 0);
693
694         rsize = MPS_SENSE_LEN * sc->num_reqs;
695         if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
696                                 1, 0,                   /* algnmnt, boundary */
697                                 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
698                                 BUS_SPACE_MAXADDR,      /* highaddr */
699                                 NULL, NULL,             /* filter, filterarg */
700                                 rsize,                  /* maxsize */
701                                 1,                      /* nsegments */
702                                 rsize,                  /* maxsegsize */
703                                 0,                      /* flags */
704                                 &sc->sense_dmat)) {
705                 device_printf(sc->mps_dev, "Cannot allocate sense DMA tag\n");
706                 return (ENOMEM);
707         }
708         if (bus_dmamem_alloc(sc->sense_dmat, (void **)&sc->sense_frames,
709             BUS_DMA_NOWAIT, &sc->sense_map)) {
710                 device_printf(sc->mps_dev, "Cannot allocate sense memory\n");
711                 return (ENOMEM);
712         }
713         bzero(sc->sense_frames, rsize);
714         bus_dmamap_load(sc->sense_dmat, sc->sense_map, sc->sense_frames, rsize,
715             mps_memaddr_cb, &sc->sense_busaddr, 0);
716
717         sc->chains = kmalloc(sizeof(struct mps_chain) * MPS_CHAIN_FRAMES,
718             M_MPT2, M_WAITOK | M_ZERO);
719         for (i = 0; i < MPS_CHAIN_FRAMES; i++) {
720                 chain = &sc->chains[i];
721                 chain->chain = (MPI2_SGE_IO_UNION *)(sc->chain_frames +
722                     i * sc->facts->IOCRequestFrameSize * 4);
723                 chain->chain_busaddr = sc->chain_busaddr +
724                     i * sc->facts->IOCRequestFrameSize * 4;
725                 mps_free_chain(sc, chain);
726         }
727
728         /* XXX Need to pick a more precise value */
729         nsegs = (MAXPHYS / PAGE_SIZE) + 1;
730         if (bus_dma_tag_create( sc->mps_parent_dmat,    /* parent */
731                                 1, 0,                   /* algnmnt, boundary */
732                                 BUS_SPACE_MAXADDR,      /* lowaddr */
733                                 BUS_SPACE_MAXADDR,      /* highaddr */
734                                 NULL, NULL,             /* filter, filterarg */
735                                 BUS_SPACE_MAXSIZE_32BIT,/* maxsize */
736                                 nsegs,                  /* nsegments */
737                                 BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
738                                 BUS_DMA_ALLOCNOW,       /* flags */
739                                 &sc->buffer_dmat)) {
740                 device_printf(sc->mps_dev, "Cannot allocate sense DMA tag\n");
741                 return (ENOMEM);
742         }
743
744         /*
745          * SMID 0 cannot be used as a free command per the firmware spec.
746          * Just drop that command instead of risking accounting bugs.
747          */
748         sc->commands = kmalloc(sizeof(struct mps_command) * sc->num_reqs,
749             M_MPT2, M_WAITOK | M_ZERO);
750         for (i = 1; i < sc->num_reqs; i++) {
751                 cm = &sc->commands[i];
752                 cm->cm_req = sc->req_frames +
753                     i * sc->facts->IOCRequestFrameSize * 4;
754                 cm->cm_req_busaddr = sc->req_busaddr +
755                     i * sc->facts->IOCRequestFrameSize * 4;
756                 cm->cm_sense = &sc->sense_frames[i];
757                 cm->cm_sense_busaddr = sc->sense_busaddr + i * MPS_SENSE_LEN;
758                 cm->cm_desc.Default.SMID = i;
759                 cm->cm_sc = sc;
760                 TAILQ_INIT(&cm->cm_chain_list);
761                 callout_init(&cm->cm_callout);
762
763                 /* XXX Is a failure here a critical problem? */
764                 if (bus_dmamap_create(sc->buffer_dmat, 0, &cm->cm_dmamap) == 0)
765                         mps_free_command(sc, cm);
766                 else {
767                         sc->num_reqs = i;
768                         break;
769                 }
770         }
771
772         return (0);
773 }
774
775 static int
776 mps_init_queues(struct mps_softc *sc)
777 {
778         int i;
779
780         memset((uint8_t *)sc->post_queue, 0xff, sc->pqdepth * 8);
781
782         /*
783          * According to the spec, we need to use one less reply than we
784          * have space for on the queue.  So sc->num_replies (the number we
785          * use) should be less than sc->fqdepth (allocated size).
786          */
787         if (sc->num_replies >= sc->fqdepth)
788                 return (EINVAL);
789
790         /*
791          * Initialize all of the free queue entries.
792          */
793         for (i = 0; i < sc->fqdepth; i++)
794                 sc->free_queue[i] = sc->reply_busaddr + (i * sc->facts->ReplyFrameSize * 4);
795         sc->replyfreeindex = sc->num_replies;
796
797         return (0);
798 }
799
800 int
801 mps_attach(struct mps_softc *sc)
802 {
803         int i, error;
804         char tmpstr[80], tmpstr2[80];
805
806         /*
807          * Grab any tunable-set debug level so that tracing works as early
808          * as possible.
809          */
810         ksnprintf(tmpstr, sizeof(tmpstr), "hw.mps.%d.debug_level",
811             device_get_unit(sc->mps_dev));
812         TUNABLE_INT_FETCH(tmpstr, &sc->mps_debug);
813         ksnprintf(tmpstr, sizeof(tmpstr), "hw.mps.%d.allow_multiple_tm_cmds",
814             device_get_unit(sc->mps_dev));
815         TUNABLE_INT_FETCH(tmpstr, &sc->allow_multiple_tm_cmds);
816
817         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
818
819         lockinit(&sc->mps_lock, "MPT2SAS lock", 0, LK_CANRECURSE);
820         callout_init(&sc->periodic);
821         TAILQ_INIT(&sc->event_list);
822
823         /*
824          * Setup the sysctl variable so the user can change the debug level
825          * on the fly.
826          */
827         ksnprintf(tmpstr, sizeof(tmpstr), "MPS controller %d",
828             device_get_unit(sc->mps_dev));
829         ksnprintf(tmpstr2, sizeof(tmpstr2), "%d", device_get_unit(sc->mps_dev));
830
831         sysctl_ctx_init(&sc->sysctl_ctx);
832         sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
833             SYSCTL_STATIC_CHILDREN(_hw_mps), OID_AUTO, tmpstr2, CTLFLAG_RD,
834             0, tmpstr);
835         if (sc->sysctl_tree == NULL)
836                 return (ENOMEM);
837
838         SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
839             OID_AUTO, "debug_level", CTLFLAG_RW, &sc->mps_debug, 0,
840             "mps debug level");
841
842         SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
843             OID_AUTO, "allow_multiple_tm_cmds", CTLFLAG_RW,
844             &sc->allow_multiple_tm_cmds, 0,
845             "allow multiple simultaneous task management cmds");
846
847         if ((error = mps_transition_ready(sc)) != 0)
848                 return (error);
849
850         sc->facts = kmalloc(sizeof(MPI2_IOC_FACTS_REPLY), M_MPT2,
851             M_ZERO|M_NOWAIT);
852         if ((error = mps_get_iocfacts(sc, sc->facts)) != 0)
853                 return (error);
854
855         mps_print_iocfacts(sc, sc->facts);
856
857         mps_printf(sc, "Firmware: %02d.%02d.%02d.%02d\n",
858             sc->facts->FWVersion.Struct.Major,
859             sc->facts->FWVersion.Struct.Minor,
860             sc->facts->FWVersion.Struct.Unit,
861             sc->facts->FWVersion.Struct.Dev);
862         mps_printf(sc, "IOCCapabilities: %b\n",
863             (u_int)(sc->facts->IOCCapabilities),
864             "\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf"
865             "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR"
866             "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc");
867
868         /*
869          * If the chip doesn't support event replay then a hard reset will be
870          * required to trigger a full discovery.  Do the reset here then
871          * retransition to Ready.  A hard reset might have already been done,
872          * but it doesn't hurt to do it again.
873          */
874         if ((sc->facts->IOCCapabilities &
875             MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) == 0) {
876                 mps_hard_reset(sc);
877                 if ((error = mps_transition_ready(sc)) != 0)
878                         return (error);
879         }
880
881         /*
882          * Size the queues. Since the reply queues always need one free entry,
883          * we'll just deduct one reply message here.
884          */
885         sc->num_reqs = MIN(MPS_REQ_FRAMES, sc->facts->RequestCredit);
886         sc->num_replies = MIN(MPS_REPLY_FRAMES + MPS_EVT_REPLY_FRAMES,
887             sc->facts->MaxReplyDescriptorPostQueueDepth) - 1;
888         TAILQ_INIT(&sc->req_list);
889         TAILQ_INIT(&sc->chain_list);
890         TAILQ_INIT(&sc->tm_list);
891
892         if (((error = mps_alloc_queues(sc)) != 0) ||
893             ((error = mps_alloc_replies(sc)) != 0) ||
894             ((error = mps_alloc_requests(sc)) != 0)) {
895                 mps_free(sc);
896                 return (error);
897         }
898
899         if (((error = mps_init_queues(sc)) != 0) ||
900             ((error = mps_transition_operational(sc)) != 0)) {
901                 mps_free(sc);
902                 return (error);
903         }
904
905         /*
906          * Finish the queue initialization.
907          * These are set here instead of in mps_init_queues() because the
908          * IOC resets these values during the state transition in
909          * mps_transition_operational().  The free index is set to 1
910          * because the corresponding index in the IOC is set to 0, and the
911          * IOC treats the queues as full if both are set to the same value.
912          * Hence the reason that the queue can't hold all of the possible
913          * replies.
914          */
915         sc->replypostindex = 0;
916         mps_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex);
917         mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, 0);
918
919         sc->pfacts = kmalloc(sizeof(MPI2_PORT_FACTS_REPLY) *
920             sc->facts->NumberOfPorts, M_MPT2, M_ZERO|M_WAITOK);
921         for (i = 0; i < sc->facts->NumberOfPorts; i++) {
922                 if ((error = mps_get_portfacts(sc, &sc->pfacts[i], i)) != 0) {
923                         mps_free(sc);
924                         return (error);
925                 }
926                 mps_print_portfacts(sc, &sc->pfacts[i]);
927         }
928
929         /* Attach the subsystems so they can prepare their event masks. */
930         /* XXX Should be dynamic so that IM/IR and user modules can attach */
931         if (((error = mps_attach_log(sc)) != 0) ||
932             ((error = mps_attach_sas(sc)) != 0) ||
933             ((error = mps_attach_user(sc)) != 0)) {
934                 mps_printf(sc, "%s failed to attach all subsystems: error %d\n",
935                     __func__, error);
936                 mps_free(sc);
937                 return (error);
938         }
939
940         if ((error = mps_pci_setup_interrupts(sc)) != 0) {
941                 mps_free(sc);
942                 return (error);
943         }
944
945         /* Start the periodic watchdog check on the IOC Doorbell */
946         mps_periodic(sc);
947
948         /*
949          * The portenable will kick off discovery events that will drive the
950          * rest of the initialization process.  The CAM/SAS module will
951          * hold up the boot sequence until discovery is complete.
952          */
953         sc->mps_ich.ich_func = mps_startup;
954         sc->mps_ich.ich_arg = sc;
955         if (config_intrhook_establish(&sc->mps_ich) != 0) {
956                 mps_dprint(sc, MPS_FAULT, "Cannot establish MPS config hook\n");
957                 error = EINVAL;
958         }
959
960         return (error);
961 }
962
963 static void
964 mps_startup(void *arg)
965 {
966         struct mps_softc *sc;
967
968         sc = (struct mps_softc *)arg;
969
970         mps_lock(sc);
971         mps_unmask_intr(sc);
972         mps_send_portenable(sc);
973         mps_unlock(sc);
974 }
975
976 /* Periodic watchdog.  Is called with the driver lock already held. */
977 static void
978 mps_periodic(void *arg)
979 {
980         struct mps_softc *sc;
981         uint32_t db;
982
983         sc = (struct mps_softc *)arg;
984         if (sc->mps_flags & MPS_FLAGS_SHUTDOWN)
985                 return;
986
987         db = mps_regread(sc, MPI2_DOORBELL_OFFSET);
988         if ((db & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
989                 device_printf(sc->mps_dev, "IOC Fault 0x%08x, Resetting\n", db);
990                 /* XXX Need to broaden this to re-initialize the chip */
991                 mps_hard_reset(sc);
992                 db = mps_regread(sc, MPI2_DOORBELL_OFFSET);
993                 if ((db & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
994                         device_printf(sc->mps_dev, "Second IOC Fault 0x%08x, "
995                             "Giving up!\n", db);
996                         return;
997                 }
998         }
999
1000         callout_reset(&sc->periodic, MPS_PERIODIC_DELAY * hz, mps_periodic, sc);
1001 }
1002
1003 static void
1004 mps_startup_complete(struct mps_softc *sc, struct mps_command *cm)
1005 {
1006         MPI2_PORT_ENABLE_REPLY *reply;
1007
1008         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1009
1010         reply = (MPI2_PORT_ENABLE_REPLY *)cm->cm_reply;
1011         if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
1012                 mps_dprint(sc, MPS_FAULT, "Portenable failed\n");
1013
1014         mps_free_command(sc, cm);
1015         config_intrhook_disestablish(&sc->mps_ich);
1016
1017 }
1018
1019 static void
1020 mps_log_evt_handler(struct mps_softc *sc, uintptr_t data,
1021     MPI2_EVENT_NOTIFICATION_REPLY *event)
1022 {
1023         MPI2_EVENT_DATA_LOG_ENTRY_ADDED *entry;
1024
1025         mps_print_event(sc, event);
1026
1027         switch (event->Event) {
1028         case MPI2_EVENT_LOG_DATA:
1029                 device_printf(sc->mps_dev, "MPI2_EVENT_LOG_DATA:\n");
1030                 hexdump(event->EventData, event->EventDataLength, NULL, 0);
1031                 break;
1032         case MPI2_EVENT_LOG_ENTRY_ADDED:
1033                 entry = (MPI2_EVENT_DATA_LOG_ENTRY_ADDED *)event->EventData;
1034                 mps_dprint(sc, MPS_INFO, "MPI2_EVENT_LOG_ENTRY_ADDED event "
1035                     "0x%x Sequence %d:\n", entry->LogEntryQualifier,
1036                      entry->LogSequence);
1037                 break;
1038         default:
1039                 break;
1040         }
1041         return;
1042 }
1043
1044 static int
1045 mps_attach_log(struct mps_softc *sc)
1046 {
1047         uint8_t events[16];
1048
1049         bzero(events, 16);
1050         setbit(events, MPI2_EVENT_LOG_DATA);
1051         setbit(events, MPI2_EVENT_LOG_ENTRY_ADDED);
1052
1053         mps_register_events(sc, events, mps_log_evt_handler, NULL,
1054             &sc->mps_log_eh);
1055
1056         return (0);
1057 }
1058
1059 static int
1060 mps_detach_log(struct mps_softc *sc)
1061 {
1062
1063         if (sc->mps_log_eh != NULL)
1064                 mps_deregister_events(sc, sc->mps_log_eh);
1065         return (0);
1066 }
1067
1068 /*
1069  * Free all of the driver resources and detach submodules.  Should be called
1070  * without the lock held.
1071  */
1072 int
1073 mps_free(struct mps_softc *sc)
1074 {
1075         struct mps_command *cm;
1076         int i, error;
1077
1078         /* Turn off the watchdog */
1079         mps_lock(sc);
1080         sc->mps_flags |= MPS_FLAGS_SHUTDOWN;
1081         mps_unlock(sc);
1082 #if 0 /* XXX swildner */
1083         /* Lock must not be held for this */
1084         callout_drain(&sc->periodic);
1085 #endif
1086
1087         if (((error = mps_detach_log(sc)) != 0) ||
1088             ((error = mps_detach_sas(sc)) != 0))
1089                 return (error);
1090
1091         /* Put the IOC back in the READY state. */
1092         mps_lock(sc);
1093         if ((error = mps_send_mur(sc)) != 0) {
1094                 mps_unlock(sc);
1095                 return (error);
1096         }
1097         mps_unlock(sc);
1098
1099         if (sc->facts != NULL)
1100                 kfree(sc->facts, M_MPT2);
1101
1102         if (sc->pfacts != NULL)
1103                 kfree(sc->pfacts, M_MPT2);
1104
1105         if (sc->post_busaddr != 0)
1106                 bus_dmamap_unload(sc->queues_dmat, sc->queues_map);
1107         if (sc->post_queue != NULL)
1108                 bus_dmamem_free(sc->queues_dmat, sc->post_queue,
1109                     sc->queues_map);
1110         if (sc->queues_dmat != NULL)
1111                 bus_dma_tag_destroy(sc->queues_dmat);
1112
1113         if (sc->chain_busaddr != 0)
1114                 bus_dmamap_unload(sc->chain_dmat, sc->chain_map);
1115         if (sc->chain_frames != NULL)
1116                 bus_dmamem_free(sc->chain_dmat, sc->chain_frames,sc->chain_map);
1117         if (sc->chain_dmat != NULL)
1118                 bus_dma_tag_destroy(sc->chain_dmat);
1119
1120         if (sc->sense_busaddr != 0)
1121                 bus_dmamap_unload(sc->sense_dmat, sc->sense_map);
1122         if (sc->sense_frames != NULL)
1123                 bus_dmamem_free(sc->sense_dmat, sc->sense_frames,sc->sense_map);
1124         if (sc->sense_dmat != NULL)
1125                 bus_dma_tag_destroy(sc->sense_dmat);
1126
1127         if (sc->reply_busaddr != 0)
1128                 bus_dmamap_unload(sc->reply_dmat, sc->reply_map);
1129         if (sc->reply_frames != NULL)
1130                 bus_dmamem_free(sc->reply_dmat, sc->reply_frames,sc->reply_map);
1131         if (sc->reply_dmat != NULL)
1132                 bus_dma_tag_destroy(sc->reply_dmat);
1133
1134         if (sc->req_busaddr != 0)
1135                 bus_dmamap_unload(sc->req_dmat, sc->req_map);
1136         if (sc->req_frames != NULL)
1137                 bus_dmamem_free(sc->req_dmat, sc->req_frames, sc->req_map);
1138         if (sc->req_dmat != NULL)
1139                 bus_dma_tag_destroy(sc->req_dmat);
1140
1141         if (sc->chains != NULL)
1142                 kfree(sc->chains, M_MPT2);
1143         if (sc->commands != NULL) {
1144                 for (i = 1; i < sc->num_reqs; i++) {
1145                         cm = &sc->commands[i];
1146                         bus_dmamap_destroy(sc->buffer_dmat, cm->cm_dmamap);
1147                 }
1148                 kfree(sc->commands, M_MPT2);
1149         }
1150         if (sc->buffer_dmat != NULL)
1151                 bus_dma_tag_destroy(sc->buffer_dmat);
1152
1153         if (sc->sysctl_tree != NULL)
1154                 sysctl_ctx_free(&sc->sysctl_ctx);
1155
1156         lockuninit(&sc->mps_lock);
1157
1158         return (0);
1159 }
1160
1161 void
1162 mps_intr(void *data)
1163 {
1164         struct mps_softc *sc;
1165         uint32_t status;
1166
1167         sc = (struct mps_softc *)data;
1168         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1169
1170         /*
1171          * Check interrupt status register to flush the bus.  This is
1172          * needed for both INTx interrupts and driver-driven polling
1173          */
1174         status = mps_regread(sc, MPI2_HOST_INTERRUPT_STATUS_OFFSET);
1175         if ((status & MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT) == 0)
1176                 return;
1177
1178         mps_lock(sc);
1179         mps_intr_locked(data);
1180         mps_unlock(sc);
1181         return;
1182 }
1183
1184 /*
1185  * In theory, MSI/MSIX interrupts shouldn't need to read any registers on the
1186  * chip.  Hopefully this theory is correct.
1187  */
1188 void
1189 mps_intr_msi(void *data)
1190 {
1191         struct mps_softc *sc;
1192
1193         sc = (struct mps_softc *)data;
1194         mps_lock(sc);
1195         mps_intr_locked(data);
1196         mps_unlock(sc);
1197         return;
1198 }
1199
1200 /*
1201  * The locking is overly broad and simplistic, but easy to deal with for now.
1202  */
1203 void
1204 mps_intr_locked(void *data)
1205 {
1206         MPI2_REPLY_DESCRIPTORS_UNION *desc;
1207         struct mps_softc *sc;
1208         struct mps_command *cm = NULL;
1209         uint8_t flags;
1210         u_int pq;
1211
1212         sc = (struct mps_softc *)data;
1213
1214         pq = sc->replypostindex;
1215
1216         for ( ;; ) {
1217                 cm = NULL;
1218                 desc = &sc->post_queue[pq];
1219                 flags = desc->Default.ReplyFlags &
1220                     MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
1221                 if ((flags == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
1222                  || (desc->Words.High == 0xffffffff))
1223                         break;
1224
1225                 switch (flags) {
1226                 case MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS:
1227                         cm = &sc->commands[desc->SCSIIOSuccess.SMID];
1228                         cm->cm_reply = NULL;
1229                         break;
1230                 case MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY:
1231                 {
1232                         uint32_t baddr;
1233                         uint8_t *reply;
1234
1235                         /*
1236                          * Re-compose the reply address from the address
1237                          * sent back from the chip.  The ReplyFrameAddress
1238                          * is the lower 32 bits of the physical address of
1239                          * particular reply frame.  Convert that address to
1240                          * host format, and then use that to provide the
1241                          * offset against the virtual address base
1242                          * (sc->reply_frames).
1243                          */
1244                         baddr = le32toh(desc->AddressReply.ReplyFrameAddress);
1245                         reply = sc->reply_frames +
1246                                 (baddr - ((uint32_t)sc->reply_busaddr));
1247                         /*
1248                          * Make sure the reply we got back is in a valid
1249                          * range.  If not, go ahead and panic here, since
1250                          * we'll probably panic as soon as we deference the
1251                          * reply pointer anyway.
1252                          */
1253                         if ((reply < sc->reply_frames)
1254                          || (reply > (sc->reply_frames +
1255                              (sc->fqdepth * sc->facts->ReplyFrameSize * 4)))) {
1256                                 kprintf("%s: WARNING: reply %p out of range!\n",
1257                                        __func__, reply);
1258                                 kprintf("%s: reply_frames %p, fqdepth %d, "
1259                                        "frame size %d\n", __func__,
1260                                        sc->reply_frames, sc->fqdepth,
1261                                        sc->facts->ReplyFrameSize * 4);
1262                                 kprintf("%s: baddr %#x,\n", __func__, baddr);
1263                                 panic("Reply address out of range");
1264                         }
1265                         if (desc->AddressReply.SMID == 0) {
1266                                 mps_dispatch_event(sc, baddr,
1267                                    (MPI2_EVENT_NOTIFICATION_REPLY *) reply);
1268                         } else {
1269                                 cm = &sc->commands[desc->AddressReply.SMID];
1270                                 cm->cm_reply = reply;
1271                                 cm->cm_reply_data =
1272                                     desc->AddressReply.ReplyFrameAddress;
1273                         }
1274                         break;
1275                 }
1276                 case MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS:
1277                 case MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER:
1278                 case MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS:
1279                 default:
1280                         /* Unhandled */
1281                         device_printf(sc->mps_dev, "Unhandled reply 0x%x\n",
1282                             desc->Default.ReplyFlags);
1283                         cm = NULL;
1284                         break;
1285                 }
1286
1287                 if (cm != NULL) {
1288                         if (cm->cm_flags & MPS_CM_FLAGS_POLLED)
1289                                 cm->cm_flags |= MPS_CM_FLAGS_COMPLETE;
1290
1291                         if (cm->cm_complete != NULL)
1292                                 cm->cm_complete(sc, cm);
1293
1294                         if (cm->cm_flags & MPS_CM_FLAGS_WAKEUP)
1295                                 wakeup(cm);
1296                 }
1297
1298                 desc->Words.Low = 0xffffffff;
1299                 desc->Words.High = 0xffffffff;
1300                 if (++pq >= sc->pqdepth)
1301                         pq = 0;
1302         }
1303
1304         if (pq != sc->replypostindex) {
1305                 mps_dprint(sc, MPS_INFO, "writing postindex %d\n", pq);
1306                 mps_regwrite(sc, MPI2_REPLY_POST_HOST_INDEX_OFFSET, pq);
1307                 sc->replypostindex = pq;
1308         }
1309
1310         return;
1311 }
1312
1313 static void
1314 mps_dispatch_event(struct mps_softc *sc, uintptr_t data,
1315     MPI2_EVENT_NOTIFICATION_REPLY *reply)
1316 {
1317         struct mps_event_handle *eh;
1318         int event, handled = 0;
1319
1320         event = reply->Event;
1321         TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
1322                 if (isset(eh->mask, event)) {
1323                         eh->callback(sc, data, reply);
1324                         handled++;
1325                 }
1326         }
1327
1328         if (handled == 0)
1329                 device_printf(sc->mps_dev, "Unhandled event 0x%x\n", event);
1330 }
1331
1332 /*
1333  * For both register_events and update_events, the caller supplies a bitmap
1334  * of events that it _wants_.  These functions then turn that into a bitmask
1335  * suitable for the controller.
1336  */
1337 int
1338 mps_register_events(struct mps_softc *sc, uint8_t *mask,
1339     mps_evt_callback_t *cb, void *data, struct mps_event_handle **handle)
1340 {
1341         struct mps_event_handle *eh;
1342         int error = 0;
1343
1344         eh = kmalloc(sizeof(struct mps_event_handle), M_MPT2, M_WAITOK|M_ZERO);
1345         eh->callback = cb;
1346         eh->data = data;
1347         TAILQ_INSERT_TAIL(&sc->event_list, eh, eh_list);
1348         if (mask != NULL)
1349                 error = mps_update_events(sc, eh, mask);
1350         *handle = eh;
1351
1352         return (error);
1353 }
1354
1355 int
1356 mps_update_events(struct mps_softc *sc, struct mps_event_handle *handle,
1357     uint8_t *mask)
1358 {
1359         MPI2_EVENT_NOTIFICATION_REQUEST *evtreq;
1360         MPI2_EVENT_NOTIFICATION_REPLY *reply;
1361         struct mps_command *cm;
1362         struct mps_event_handle *eh;
1363         int error, i;
1364
1365         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1366
1367         if ((mask != NULL) && (handle != NULL))
1368                 bcopy(mask, &handle->mask[0], 16);
1369         memset(sc->event_mask, 0xff, 16);
1370
1371         TAILQ_FOREACH(eh, &sc->event_list, eh_list) {
1372                 for (i = 0; i < 16; i++)
1373                         sc->event_mask[i] &= ~eh->mask[i];
1374         }
1375
1376         if ((cm = mps_alloc_command(sc)) == NULL)
1377                 return (EBUSY);
1378         evtreq = (MPI2_EVENT_NOTIFICATION_REQUEST *)cm->cm_req;
1379         evtreq->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
1380         evtreq->MsgFlags = 0;
1381         evtreq->SASBroadcastPrimitiveMasks = 0;
1382 #ifdef MPS_DEBUG_ALL_EVENTS
1383         {
1384                 u_char fullmask[16];
1385                 memset(fullmask, 0x00, 16);
1386                 bcopy(fullmask, (uint8_t *)&evtreq->EventMasks, 16);
1387         }
1388 #else
1389                 bcopy(sc->event_mask, (uint8_t *)&evtreq->EventMasks, 16);
1390 #endif
1391         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1392         cm->cm_data = NULL;
1393
1394         error = mps_request_polled(sc, cm);
1395         reply = (MPI2_EVENT_NOTIFICATION_REPLY *)cm->cm_reply;
1396         if ((reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
1397                 error = ENXIO;
1398         mps_print_event(sc, reply);
1399
1400         mps_free_command(sc, cm);
1401         return (error);
1402 }
1403
1404 int
1405 mps_deregister_events(struct mps_softc *sc, struct mps_event_handle *handle)
1406 {
1407
1408         TAILQ_REMOVE(&sc->event_list, handle, eh_list);
1409         kfree(handle, M_MPT2);
1410         return (mps_update_events(sc, NULL, NULL));
1411 }
1412
1413 /*
1414  * Add a chain element as the next SGE for the specified command.
1415  * Reset cm_sge and cm_sgesize to indicate all the available space.
1416  */
1417 static int
1418 mps_add_chain(struct mps_command *cm)
1419 {
1420         MPI2_SGE_CHAIN32 *sgc;
1421         struct mps_chain *chain;
1422         int space;
1423
1424         if (cm->cm_sglsize < MPS_SGC_SIZE)
1425                 panic("MPS: Need SGE Error Code\n");
1426
1427         chain = mps_alloc_chain(cm->cm_sc);
1428         if (chain == NULL)
1429                 return (ENOBUFS);
1430
1431         space = (int)cm->cm_sc->facts->IOCRequestFrameSize * 4;
1432
1433         /*
1434          * Note: a double-linked list is used to make it easier to
1435          * walk for debugging.
1436          */
1437         TAILQ_INSERT_TAIL(&cm->cm_chain_list, chain, chain_link);
1438
1439         sgc = (MPI2_SGE_CHAIN32 *)&cm->cm_sge->MpiChain;
1440         sgc->Length = space;
1441         sgc->NextChainOffset = 0;
1442         sgc->Flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT;
1443         sgc->Address = chain->chain_busaddr;
1444
1445         cm->cm_sge = (MPI2_SGE_IO_UNION *)&chain->chain->MpiSimple;
1446         cm->cm_sglsize = space;
1447         return (0);
1448 }
1449
1450 /*
1451  * Add one scatter-gather element (chain, simple, transaction context)
1452  * to the scatter-gather list for a command.  Maintain cm_sglsize and
1453  * cm_sge as the remaining size and pointer to the next SGE to fill
1454  * in, respectively.
1455  */
1456 int
1457 mps_push_sge(struct mps_command *cm, void *sgep, size_t len, int segsleft)
1458 {
1459         MPI2_SGE_TRANSACTION_UNION *tc = sgep;
1460         MPI2_SGE_SIMPLE64 *sge = sgep;
1461         int error, type;
1462
1463         type = (tc->Flags & MPI2_SGE_FLAGS_ELEMENT_MASK);
1464
1465 #ifdef INVARIANTS
1466         switch (type) {
1467         case MPI2_SGE_FLAGS_TRANSACTION_ELEMENT: {
1468                 if (len != tc->DetailsLength + 4)
1469                         panic("TC %p length %u or %zu?", tc,
1470                             tc->DetailsLength + 4, len);
1471                 }
1472                 break;
1473         case MPI2_SGE_FLAGS_CHAIN_ELEMENT:
1474                 /* Driver only uses 32-bit chain elements */
1475                 if (len != MPS_SGC_SIZE)
1476                         panic("CHAIN %p length %u or %zu?", sgep,
1477                             MPS_SGC_SIZE, len);
1478                 break;
1479         case MPI2_SGE_FLAGS_SIMPLE_ELEMENT:
1480                 /* Driver only uses 64-bit SGE simple elements */
1481                 sge = sgep;
1482                 if (len != MPS_SGE64_SIZE)
1483                         panic("SGE simple %p length %u or %zu?", sge,
1484                             MPS_SGE64_SIZE, len);
1485                 if (((sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT) &
1486                     MPI2_SGE_FLAGS_ADDRESS_SIZE) == 0)
1487                         panic("SGE simple %p flags %02x not marked 64-bit?",
1488                             sge,
1489                             (u_int)(sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT));
1490
1491                 break;
1492         default:
1493                 panic("Unexpected SGE %p, flags %02x", tc, tc->Flags);
1494         }
1495 #endif
1496
1497         /*
1498          * case 1: 1 more segment, enough room for it
1499          * case 2: 2 more segments, enough room for both
1500          * case 3: >=2 more segments, only enough room for 1 and a chain
1501          * case 4: >=1 more segment, enough room for only a chain
1502          * case 5: >=1 more segment, no room for anything (error)
1503          */
1504
1505         /*
1506          * There should be room for at least a chain element, or this
1507          * code is buggy.  Case (5).
1508          */
1509         if (cm->cm_sglsize < MPS_SGC_SIZE)
1510                 panic("MPS: Need SGE Error Code\n");
1511
1512         if (segsleft >= 2 &&
1513             cm->cm_sglsize < len + MPS_SGC_SIZE + MPS_SGE64_SIZE) {
1514                 /*
1515                  * There are 2 or more segments left to add, and only
1516                  * enough room for 1 and a chain.  Case (3).
1517                  *
1518                  * Mark as last element in this chain if necessary.
1519                  */
1520                 if (type == MPI2_SGE_FLAGS_SIMPLE_ELEMENT) {
1521                         sge->FlagsLength |=
1522                                 (MPI2_SGE_FLAGS_LAST_ELEMENT << MPI2_SGE_FLAGS_SHIFT);
1523                 }
1524
1525                 /*
1526                  * Add the item then a chain.  Do the chain now,
1527                  * rather than on the next iteration, to simplify
1528                  * understanding the code.
1529                  */
1530                 cm->cm_sglsize -= len;
1531                 bcopy(sgep, cm->cm_sge, len);
1532                 cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
1533                 return (mps_add_chain(cm));
1534         }
1535
1536         if (segsleft >= 1 && cm->cm_sglsize < len + MPS_SGC_SIZE) {
1537                 /*
1538                  * 1 or more segment, enough room for only a chain.
1539                  * Hope the previous element wasn't a Simple entry
1540                  * that needed to be marked with
1541                  * MPI2_SGE_FLAGS_LAST_ELEMENT.  Case (4).
1542                  */
1543                 if ((error = mps_add_chain(cm)) != 0)
1544                         return (error);
1545         }
1546
1547 #ifdef INVARIANTS
1548         /* Case 1: 1 more segment, enough room for it. */
1549         if (segsleft == 1 && cm->cm_sglsize < len)
1550                 panic("1 seg left and no room? %u versus %zu",
1551                     cm->cm_sglsize, len);
1552
1553         /* Case 2: 2 more segments, enough room for both */
1554         if (segsleft == 2 && cm->cm_sglsize < len + MPS_SGE64_SIZE)
1555                 panic("2 segs left and no room? %u versus %zu",
1556                     cm->cm_sglsize, len);
1557 #endif
1558
1559         if (segsleft == 1 && type == MPI2_SGE_FLAGS_SIMPLE_ELEMENT) {
1560                 /*
1561                  * Last element of the last segment of the entire
1562                  * buffer.
1563                  */
1564                 sge->FlagsLength |= ((MPI2_SGE_FLAGS_LAST_ELEMENT |
1565                     MPI2_SGE_FLAGS_END_OF_BUFFER |
1566                     MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
1567         }
1568
1569         cm->cm_sglsize -= len;
1570         bcopy(sgep, cm->cm_sge, len);
1571         cm->cm_sge = (MPI2_SGE_IO_UNION *)((uintptr_t)cm->cm_sge + len);
1572         return (0);
1573 }
1574
1575 /*
1576  * Add one dma segment to the scatter-gather list for a command.
1577  */
1578 int
1579 mps_add_dmaseg(struct mps_command *cm, vm_paddr_t pa, size_t len, u_int flags,
1580     int segsleft)
1581 {
1582         MPI2_SGE_SIMPLE64 sge;
1583
1584         /*
1585          * This driver always uses 64-bit address elements for
1586          * simplicity.
1587          */
1588         flags |= MPI2_SGE_FLAGS_SIMPLE_ELEMENT | MPI2_SGE_FLAGS_ADDRESS_SIZE;
1589         sge.FlagsLength = len | (flags << MPI2_SGE_FLAGS_SHIFT);
1590         mps_from_u64(pa, &sge.Address);
1591
1592         return (mps_push_sge(cm, &sge, sizeof sge, segsleft));
1593 }
1594
1595 static void
1596 mps_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
1597 {
1598         struct mps_softc *sc;
1599         struct mps_command *cm;
1600         u_int i, dir, sflags;
1601
1602         cm = (struct mps_command *)arg;
1603         sc = cm->cm_sc;
1604
1605         /*
1606          * In this case, just print out a warning and let the chip tell the
1607          * user they did the wrong thing.
1608          */
1609         if ((cm->cm_max_segs != 0) && (nsegs > cm->cm_max_segs)) {
1610                 mps_printf(sc, "%s: warning: busdma returned %d segments, "
1611                            "more than the %d allowed\n", __func__, nsegs,
1612                            cm->cm_max_segs);
1613         }
1614
1615         /*
1616          * Set up DMA direction flags.  Note that we don't support
1617          * bi-directional transfers, with the exception of SMP passthrough.
1618          */
1619         sflags = 0;
1620         if (cm->cm_flags & MPS_CM_FLAGS_SMP_PASS) {
1621                 /*
1622                  * We have to add a special case for SMP passthrough, there
1623                  * is no easy way to generically handle it.  The first
1624                  * S/G element is used for the command (therefore the
1625                  * direction bit needs to be set).  The second one is used
1626                  * for the reply.  We'll leave it to the caller to make
1627                  * sure we only have two buffers.
1628                  */
1629                 /*
1630                  * Even though the busdma man page says it doesn't make
1631                  * sense to have both direction flags, it does in this case.
1632                  * We have one s/g element being accessed in each direction.
1633                  */
1634                 dir = BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD;
1635
1636                 /*
1637                  * Set the direction flag on the first buffer in the SMP
1638                  * passthrough request.  We'll clear it for the second one.
1639                  */
1640                 sflags |= MPI2_SGE_FLAGS_DIRECTION |
1641                           MPI2_SGE_FLAGS_END_OF_BUFFER;
1642         } else if (cm->cm_flags & MPS_CM_FLAGS_DATAOUT) {
1643                 sflags |= MPI2_SGE_FLAGS_DIRECTION;
1644                 dir = BUS_DMASYNC_PREWRITE;
1645         } else
1646                 dir = BUS_DMASYNC_PREREAD;
1647
1648         for (i = 0; i < nsegs; i++) {
1649                 if ((cm->cm_flags & MPS_CM_FLAGS_SMP_PASS)
1650                  && (i != 0)) {
1651                         sflags &= ~MPI2_SGE_FLAGS_DIRECTION;
1652                 }
1653                 error = mps_add_dmaseg(cm, segs[i].ds_addr, segs[i].ds_len,
1654                     sflags, nsegs - i);
1655                 if (error != 0) {
1656                         /* Resource shortage, roll back! */
1657                         mps_printf(sc, "out of chain frames\n");
1658                         return;
1659                 }
1660         }
1661
1662         bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
1663         mps_enqueue_request(sc, cm);
1664
1665         return;
1666 }
1667
1668 static void
1669 mps_data_cb2(void *arg, bus_dma_segment_t *segs, int nsegs, bus_size_t mapsize,
1670              int error)
1671 {
1672         mps_data_cb(arg, segs, nsegs, error);
1673 }
1674
1675 /*
1676  * Note that the only error path here is from bus_dmamap_load(), which can
1677  * return EINPROGRESS if it is waiting for resources.
1678  */
1679 int
1680 mps_map_command(struct mps_softc *sc, struct mps_command *cm)
1681 {
1682         MPI2_SGE_SIMPLE32 *sge;
1683         int error = 0;
1684
1685         if (cm->cm_flags & MPS_CM_FLAGS_USE_UIO) {
1686                 error = bus_dmamap_load_uio(sc->buffer_dmat, cm->cm_dmamap,
1687                     &cm->cm_uio, mps_data_cb2, cm, 0);
1688         } else if ((cm->cm_data != NULL) && (cm->cm_length != 0)) {
1689                 error = bus_dmamap_load(sc->buffer_dmat, cm->cm_dmamap,
1690                     cm->cm_data, cm->cm_length, mps_data_cb, cm, 0);
1691         } else {
1692                 /* Add a zero-length element as needed */
1693                 if (cm->cm_sge != NULL) {
1694                         sge = (MPI2_SGE_SIMPLE32 *)cm->cm_sge;
1695                         sge->FlagsLength = (MPI2_SGE_FLAGS_LAST_ELEMENT |
1696                             MPI2_SGE_FLAGS_END_OF_BUFFER |
1697                             MPI2_SGE_FLAGS_END_OF_LIST |
1698                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
1699                             MPI2_SGE_FLAGS_SHIFT;
1700                         sge->Address = 0;
1701                 }
1702                 mps_enqueue_request(sc, cm);
1703         }
1704
1705         return (error);
1706 }
1707
1708 /*
1709  * The MPT driver had a verbose interface for config pages.  In this driver,
1710  * reduce it to much simplier terms, similar to the Linux driver.
1711  */
1712 int
1713 mps_read_config_page(struct mps_softc *sc, struct mps_config_params *params)
1714 {
1715         MPI2_CONFIG_REQUEST *req;
1716         struct mps_command *cm;
1717         int error;
1718
1719         if (sc->mps_flags & MPS_FLAGS_BUSY) {
1720                 return (EBUSY);
1721         }
1722
1723         cm = mps_alloc_command(sc);
1724         if (cm == NULL) {
1725                 return (EBUSY);
1726         }
1727
1728         req = (MPI2_CONFIG_REQUEST *)cm->cm_req;
1729         req->Function = MPI2_FUNCTION_CONFIG;
1730         req->Action = params->action;
1731         req->SGLFlags = 0;
1732         req->ChainOffset = 0;
1733         req->PageAddress = params->page_address;
1734         if (params->hdr.Ext.ExtPageType != 0) {
1735                 MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
1736
1737                 hdr = &params->hdr.Ext;
1738                 req->ExtPageType = hdr->ExtPageType;
1739                 req->ExtPageLength = hdr->ExtPageLength;
1740                 req->Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
1741                 req->Header.PageLength = 0; /* Must be set to zero */
1742                 req->Header.PageNumber = hdr->PageNumber;
1743                 req->Header.PageVersion = hdr->PageVersion;
1744         } else {
1745                 MPI2_CONFIG_PAGE_HEADER *hdr;
1746
1747                 hdr = &params->hdr.Struct;
1748                 req->Header.PageType = hdr->PageType;
1749                 req->Header.PageNumber = hdr->PageNumber;
1750                 req->Header.PageLength = hdr->PageLength;
1751                 req->Header.PageVersion = hdr->PageVersion;
1752         }
1753
1754         cm->cm_data = params->buffer;
1755         cm->cm_length = params->length;
1756         cm->cm_sge = &req->PageBufferSGE;
1757         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
1758         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
1759         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1760
1761         cm->cm_complete_data = params;
1762         if (params->callback != NULL) {
1763                 cm->cm_complete = mps_config_complete;
1764                 return (mps_map_command(sc, cm));
1765         } else {
1766                 cm->cm_complete = NULL;
1767                 cm->cm_flags |= MPS_CM_FLAGS_WAKEUP;
1768                 if ((error = mps_map_command(sc, cm)) != 0)
1769                         return (error);
1770                 lksleep(cm, &sc->mps_lock, 0, "mpswait", 0);
1771                 mps_config_complete(sc, cm);
1772         }
1773
1774         return (0);
1775 }
1776
1777 int
1778 mps_write_config_page(struct mps_softc *sc, struct mps_config_params *params)
1779 {
1780         return (EINVAL);
1781 }
1782
1783 static void
1784 mps_config_complete(struct mps_softc *sc, struct mps_command *cm)
1785 {
1786         MPI2_CONFIG_REPLY *reply;
1787         struct mps_config_params *params;
1788
1789         params = cm->cm_complete_data;
1790
1791         if (cm->cm_data != NULL) {
1792                 bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap,
1793                     BUS_DMASYNC_POSTREAD);
1794                 bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
1795         }
1796
1797         reply = (MPI2_CONFIG_REPLY *)cm->cm_reply;
1798         params->status = reply->IOCStatus;
1799         if (params->hdr.Ext.ExtPageType != 0) {
1800                 params->hdr.Ext.ExtPageType = reply->ExtPageType;
1801                 params->hdr.Ext.ExtPageLength = reply->ExtPageLength;
1802         } else {
1803                 params->hdr.Struct.PageType = reply->Header.PageType;
1804                 params->hdr.Struct.PageNumber = reply->Header.PageNumber;
1805                 params->hdr.Struct.PageLength = reply->Header.PageLength;
1806                 params->hdr.Struct.PageVersion = reply->Header.PageVersion;
1807         }
1808
1809         mps_free_command(sc, cm);
1810         if (params->callback != NULL)
1811                 params->callback(sc, params);
1812
1813         return;
1814 }