kernel: Add D_MPSAFE to the ops of mfi(4), mrsas(4) and twa(4).
[dragonfly.git] / sys / dev / raid / mrsas / mrsas_ioctl.c
1 /*
2  * Copyright (c) 2014, LSI Corp.
3  * All rights reserved.
4  * Author: Marian Choy
5  * Support: freebsdraid@lsi.com
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of the <ORGANIZATION> nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * The views and conclusions contained in the software and documentation
35  * are those of the authors and should not be interpreted as representing
36  * official policies,either expressed or implied, of the FreeBSD Project.
37  *
38  * Send feedback to: <megaraidfbsd@lsi.com>
39  * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
40  *    ATTN: MegaRaid FreeBSD
41  *
42  * $FreeBSD: head/sys/dev/mrsas/mrsas_ioctl.c 265555 2014-05-07 16:16:49Z ambrisko $
43  */
44
45 #include <dev/raid/mrsas/mrsas.h>
46 #include <dev/raid/mrsas/mrsas_ioctl.h>
47
48 /* 
49  * Function prototypes 
50  */
51 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
52 int mrsas_passthru(struct mrsas_softc *sc, void *arg);
53 void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
54 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
55 void mrsas_dump_dcmd(struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd);
56 void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc);
57 void * mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
58 static int mrsas_create_frame_pool(struct mrsas_softc *sc);
59 static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
60         int nsegs, int error);
61
62 extern struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc);
63 extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
64 extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
65     struct mrsas_mfi_cmd *cmd);
66
67
68 /**
69  * mrsas_dump_ioctl:       Print debug output for DCMDs 
70  * input:                  Adapter instance soft state
71  *                         DCMD frame structure
72  *
73  * This function is called from mrsas_passthru() to print out debug information
74  * in the handling and routing of DCMD commands.
75  */
76 void mrsas_dump_dcmd( struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd )
77 {
78     int i;
79
80     device_printf(sc->mrsas_dev, "dcmd->cmd:           0x%02hhx\n", dcmd->cmd);
81     device_printf(sc->mrsas_dev, "dcmd->cmd_status:    0x%02hhx\n", dcmd->cmd_status);
82     device_printf(sc->mrsas_dev, "dcmd->sge_count:     0x%02hhx\n", dcmd->sge_count);
83     device_printf(sc->mrsas_dev, "dcmd->context:       0x%08x\n", dcmd->context);
84     device_printf(sc->mrsas_dev, "dcmd->flags:         0x%04hx\n", dcmd->flags);
85     device_printf(sc->mrsas_dev, "dcmd->timeout:       0x%04hx\n", dcmd->timeout);
86     device_printf(sc->mrsas_dev, "dcmd->data_xfer_len: 0x%08x\n", dcmd->data_xfer_len);
87     device_printf(sc->mrsas_dev, "dcmd->opcode:        0x%08x\n", dcmd->opcode);
88     device_printf(sc->mrsas_dev, "dcmd->mbox.w[0]:     0x%08x\n", dcmd->mbox.w[0]);
89     device_printf(sc->mrsas_dev, "dcmd->mbox.w[1]:     0x%08x\n", dcmd->mbox.w[1]);
90     device_printf(sc->mrsas_dev, "dcmd->mbox.w[2]:     0x%08x\n", dcmd->mbox.w[2]);
91     for (i=0; i< MIN(MAX_IOCTL_SGE, dcmd->sge_count); i++) {
92         device_printf(sc->mrsas_dev, "sgl[%02d]\n", i);
93         device_printf(sc->mrsas_dev, "    sge32[%02d].phys_addr: 0x%08x\n",  
94             i, dcmd->sgl.sge32[i].phys_addr);
95         device_printf(sc->mrsas_dev, "    sge32[%02d].length:    0x%08x\n", 
96             i, dcmd->sgl.sge32[i].length);
97         device_printf(sc->mrsas_dev, "    sge64[%02d].phys_addr: 0x%08llx\n",
98             i, (unsigned long long) dcmd->sgl.sge64[i].phys_addr);
99         device_printf(sc->mrsas_dev, "    sge64[%02d].length:    0x%08x\n", 
100             i, dcmd->sgl.sge64[i].length);
101     }
102 }
103
104 /**
105  * mrsas_dump_ioctl:       Print debug output for ioctl 
106  * input:                  Adapter instance soft state
107  *                         iocpacket structure 
108  *
109  * This function is called from mrsas_passthru() to print out debug information
110  * in the handling and routing of ioctl commands.
111  */
112 void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc)
113 {
114     union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw);
115     struct mrsas_dcmd_frame* dcmd = (struct mrsas_dcmd_frame *) &(in_cmd->dcmd);
116     int i;
117  
118     device_printf(sc->mrsas_dev, 
119         "====== In %s() ======================================\n", __func__);
120     device_printf(sc->mrsas_dev, "host_no:    0x%04hx\n", user_ioc->host_no);
121     device_printf(sc->mrsas_dev, " __pad1:    0x%04hx\n", user_ioc->__pad1);
122     device_printf(sc->mrsas_dev, "sgl_off:    0x%08x\n",  user_ioc->sgl_off);
123     device_printf(sc->mrsas_dev, "sge_count:  0x%08x\n",  user_ioc->sge_count);
124     device_printf(sc->mrsas_dev, "sense_off:  0x%08x\n",  user_ioc->sense_off);
125     device_printf(sc->mrsas_dev, "sense_len:  0x%08x\n",  user_ioc->sense_len);
126
127     mrsas_dump_dcmd(sc, dcmd);
128
129     for (i=0; i< MIN(MAX_IOCTL_SGE, user_ioc->sge_count); i++) {
130         device_printf(sc->mrsas_dev, "sge[%02d]\n", i);
131         device_printf(sc->mrsas_dev, 
132             "    iov_base: %p\n", user_ioc->sgl[i].iov_base);
133         device_printf(sc->mrsas_dev, "    iov_len:  %p\n", 
134             (void*)user_ioc->sgl[i].iov_len);
135     }
136     device_printf(sc->mrsas_dev, 
137         "==================================================================\n");
138 }
139
140 /**
141  * mrsas_passthru:        Handle pass-through commands 
142  * input:                 Adapter instance soft state
143  *                        argument pointer
144  *
145  * This function is called from mrsas_ioctl() to handle pass-through and 
146  * ioctl commands to Firmware.  
147  */
148 int mrsas_passthru( struct mrsas_softc *sc, void *arg )
149 {
150     struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
151     union  mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw);
152     struct mrsas_mfi_cmd *cmd = NULL;
153     bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE];
154     bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE];
155     void *ioctl_data_mem[MAX_IOCTL_SGE];  // ioctl data virtual addr
156     bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE]; // ioctl data phys addr
157     bus_dma_tag_t ioctl_sense_tag = 0;
158     bus_dmamap_t ioctl_sense_dmamap = 0;
159     void *ioctl_sense_mem = NULL;  
160     bus_addr_t ioctl_sense_phys_addr = 0; 
161     int i, adapter, ioctl_data_size, ioctl_sense_size, ret=0;
162     struct mrsas_sge32 *kern_sge32;
163     unsigned long *sense_ptr;
164
165     /* For debug - uncomment the following line for debug output */
166     //mrsas_dump_ioctl(sc, user_ioc); 
167
168     /* 
169      * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0.  In this 
170      * case do nothing and return 0 to it as status.
171      */
172     if (in_cmd->dcmd.opcode == 0) {
173         device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__);
174         user_ioc->frame.hdr.cmd_status = MFI_STAT_OK;
175         return (0);
176     }
177
178     /* Validate host_no */
179     adapter = user_ioc->host_no;
180     if (adapter != device_get_unit(sc->mrsas_dev)) {
181         device_printf(sc->mrsas_dev, "In %s() IOCTL not for me!\n", __func__);
182         return(ENOENT);
183     }
184
185     /* Validate SGL length */
186     if (user_ioc->sge_count > MAX_IOCTL_SGE) { 
187         device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n", 
188             __func__, user_ioc->sge_count);
189         return(ENOENT);
190     }
191
192     /* Get a command */
193     cmd = mrsas_get_mfi_cmd(sc);
194     if (!cmd) {
195         device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n");
196         return(ENOMEM);
197     }
198
199     /*
200      * User's IOCTL packet has 2 frames (maximum). Copy those two
201      * frames into our cmd's frames. cmd->frame's context will get
202      * overwritten when we copy from user's frames. So set that value
203      * alone separately
204      */
205     memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
206     cmd->frame->hdr.context = cmd->index;
207     cmd->frame->hdr.pad_0 = 0;
208     cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
209                                MFI_FRAME_SENSE64);
210
211     /*
212      * The management interface between applications and the fw uses
213      * MFI frames. E.g, RAID configuration changes, LD property changes
214      * etc are accomplishes through different kinds of MFI frames. The
215      * driver needs to care only about substituting user buffers with
216      * kernel buffers in SGLs. The location of SGL is embedded in the
217      * struct iocpacket itself.
218      */
219     kern_sge32 = (struct mrsas_sge32 *)
220         ((unsigned long)cmd->frame + user_ioc->sgl_off);
221
222     /*
223      * For each user buffer, create a mirror buffer and copy in
224      */
225     for (i=0; i < user_ioc->sge_count; i++) {
226         if (!user_ioc->sgl[i].iov_len)
227             continue;
228         ioctl_data_size = user_ioc->sgl[i].iov_len;
229         if (bus_dma_tag_create( sc->mrsas_parent_tag,   // parent
230                                 1, 0,                   // algnmnt, boundary
231                                 BUS_SPACE_MAXADDR_32BIT,// lowaddr
232                                 BUS_SPACE_MAXADDR,      // highaddr
233                                 NULL, NULL,             // filter, filterarg
234                                 ioctl_data_size,        // maxsize
235                                 1,                      // msegments
236                                 ioctl_data_size,        // maxsegsize
237                                 BUS_DMA_ALLOCNOW,       // flags
238                                 &ioctl_data_tag[i])) {
239             device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
240             return (ENOMEM);
241         }
242         if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
243                 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
244             device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
245             return (ENOMEM);
246         }
247         if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
248                 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
249                 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
250             device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
251             return (ENOMEM);
252         }
253
254         /* Save the physical address and length */
255         kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
256         kern_sge32[i].length = user_ioc->sgl[i].iov_len;
257
258         /* Copy in data from user space */
259         ret = copyin(user_ioc->sgl[i].iov_base, ioctl_data_mem[i], 
260                         user_ioc->sgl[i].iov_len);
261         if (ret) {
262             device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
263             goto out;
264         }
265     }
266
267     ioctl_sense_size = user_ioc->sense_len;
268     if (user_ioc->sense_len) {
269         if (bus_dma_tag_create( sc->mrsas_parent_tag,   // parent
270                                 1, 0,                   // algnmnt, boundary
271                                 BUS_SPACE_MAXADDR_32BIT,// lowaddr
272                                 BUS_SPACE_MAXADDR,      // highaddr
273                                 NULL, NULL,             // filter, filterarg
274                                 ioctl_sense_size,       // maxsize
275                                 1,                      // msegments
276                                 ioctl_sense_size,       // maxsegsize
277                                 BUS_DMA_ALLOCNOW,       // flags
278                                 &ioctl_sense_tag)) {
279             device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
280             return (ENOMEM);
281         }
282         if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
283                 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
284             device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
285             return (ENOMEM);
286         }
287         if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
288                 ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
289                 &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
290             device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
291             return (ENOMEM);
292         }
293         sense_ptr = 
294             (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off);
295             sense_ptr = ioctl_sense_mem;
296     }
297
298     /*
299      * Set the sync_cmd flag so that the ISR knows not to complete this
300      * cmd to the SCSI mid-layer
301      */
302     cmd->sync_cmd = 1;
303     mrsas_issue_blocked_cmd(sc, cmd);
304     cmd->sync_cmd = 0;
305
306     /*
307      * copy out the kernel buffers to user buffers
308      */
309     for (i = 0; i < user_ioc->sge_count; i++) {
310         ret = copyout(ioctl_data_mem[i], user_ioc->sgl[i].iov_base, 
311             user_ioc->sgl[i].iov_len);
312         if (ret) {
313             device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
314             goto out;
315         }
316     }
317
318     /*
319      * copy out the sense
320      */
321     if (user_ioc->sense_len) {
322         /*
323          * sense_buff points to the location that has the user
324          * sense buffer address
325          */
326         sense_ptr = (unsigned long *) ((unsigned long)user_ioc->frame.raw +
327                       user_ioc->sense_off);
328         ret = copyout(ioctl_sense_mem, (unsigned long*)*sense_ptr, 
329                       user_ioc->sense_len); 
330         if (ret) {
331             device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
332             goto out;
333         }
334     }
335
336     /*
337      * Return command status to user space
338      */
339     memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status, 
340             sizeof(u_int8_t));
341
342 out:
343     /* 
344      * Release sense buffer 
345      */
346     if (ioctl_sense_phys_addr)
347         bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
348     if (ioctl_sense_mem)
349         bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
350     if (ioctl_sense_tag)
351         bus_dma_tag_destroy(ioctl_sense_tag);
352
353     /* 
354      * Release data buffers 
355      */
356     for (i = 0; i < user_ioc->sge_count; i++) {
357         if (!user_ioc->sgl[i].iov_len)
358             continue;
359         if (ioctl_data_phys_addr[i])
360             bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
361         if (ioctl_data_mem[i] != NULL)
362             bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i], 
363                 ioctl_data_dmamap[i]);
364         if (ioctl_data_tag[i] != NULL)
365             bus_dma_tag_destroy(ioctl_data_tag[i]);
366     }
367
368     /* Free command */
369     mrsas_release_mfi_cmd(cmd);
370
371     return(ret);
372 }
373
374 /**
375  * mrsas_alloc_mfi_cmds:  Allocates the command packets
376  * input:                 Adapter instance soft state
377  *
378  * Each IOCTL or passthru command that is issued to the FW are wrapped in a
379  * local data structure called mrsas_mfi_cmd.  The frame embedded in this 
380  * mrsas_mfi is issued to FW. The array is used only to look up the 
381  * mrsas_mfi_cmd given the context. The free commands are maintained in a
382  * linked list.
383  */
384 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
385 {
386     int i, j;
387     u_int32_t max_cmd;
388     struct mrsas_mfi_cmd *cmd;
389
390     max_cmd = MRSAS_MAX_MFI_CMDS;
391
392     /*
393      * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers. Allocate the
394      * dynamic array first and then allocate individual commands.
395      */
396     sc->mfi_cmd_list = kmalloc(sizeof(struct mrsas_mfi_cmd*)*max_cmd, M_MRSAS, M_NOWAIT);
397     if (!sc->mfi_cmd_list) {
398         device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
399         return(ENOMEM);
400     }
401     memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *)*max_cmd);
402     for (i = 0; i < max_cmd; i++) {
403         sc->mfi_cmd_list[i] = kmalloc(sizeof(struct mrsas_mfi_cmd), 
404                                  M_MRSAS, M_NOWAIT);
405         if (!sc->mfi_cmd_list[i]) {
406             for (j = 0; j < i; j++)
407                 kfree(sc->mfi_cmd_list[j],M_MRSAS);
408             kfree(sc->mfi_cmd_list, M_MRSAS);
409             sc->mfi_cmd_list = NULL;
410             return(ENOMEM);
411         }
412     }
413
414     for (i = 0; i < max_cmd; i++) {
415         cmd = sc->mfi_cmd_list[i];
416         memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
417         cmd->index = i;
418         cmd->ccb_ptr = NULL;
419         cmd->sc = sc; 
420         TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
421     }
422
423     /* create a frame pool and assign one frame to each command */
424     if (mrsas_create_frame_pool(sc)) {
425         device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
426         for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) { // Free the frames
427             cmd = sc->mfi_cmd_list[i];
428             mrsas_free_frame(sc, cmd);
429         }
430         if (sc->mficmd_frame_tag != NULL)
431             bus_dma_tag_destroy(sc->mficmd_frame_tag);
432         return(ENOMEM);
433     }
434
435     return(0);
436 }
437
438 /**
439  * mrsas_create_frame_pool -   Creates DMA pool for cmd frames
440  * input:                      Adapter soft state
441  *
442  * Each command packet has an embedded DMA memory buffer that is used for
443  * filling MFI frame and the SG list that immediately follows the frame. This
444  * function creates those DMA memory buffers for each command packet by using
445  * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value 
446  * of context and could cause FW crash.
447  */
448 static int mrsas_create_frame_pool(struct mrsas_softc *sc)
449 {
450     int i;
451     struct mrsas_mfi_cmd *cmd;
452
453     if (bus_dma_tag_create( sc->mrsas_parent_tag,   // parent
454                             1, 0,                   // algnmnt, boundary
455                             BUS_SPACE_MAXADDR_32BIT,// lowaddr
456                             BUS_SPACE_MAXADDR,      // highaddr
457                             NULL, NULL,             // filter, filterarg
458                             MRSAS_MFI_FRAME_SIZE,   // maxsize
459                             1,                      // msegments
460                             MRSAS_MFI_FRAME_SIZE,   // maxsegsize
461                             BUS_DMA_ALLOCNOW,       // flags
462                             &sc->mficmd_frame_tag)) {
463         device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
464         return (ENOMEM);
465     }
466
467     for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
468         cmd = sc->mfi_cmd_list[i];
469         cmd->frame = mrsas_alloc_frame(sc, cmd);
470         if (cmd->frame == NULL) {
471             device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
472             return (ENOMEM);
473         } 
474         memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE); 
475         cmd->frame->io.context = cmd->index;
476         cmd->frame->io.pad_0 = 0;
477     }
478
479     return(0);
480 }
481
482 /**
483  * mrsas_alloc_frame -   Allocates MFI Frames
484  * input:                Adapter soft state
485  *
486  * Create bus DMA memory tag and dmamap and load memory for MFI frames. 
487  * Returns virtual memory pointer to allocated region. 
488  */
489 void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
490 {
491     u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
492
493     if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
494                     BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
495         device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
496         return (NULL);
497     }
498     if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
499                         cmd->frame_mem, frame_size, mrsas_alloc_cb,
500                         &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
501         device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
502         return (NULL);
503     }
504   
505     return(cmd->frame_mem);
506 }
507
508 /*
509  * mrsas_alloc_cb:  Callback function of bus_dmamap_load()
510  * input:           callback argument,
511  *                  machine dependent type that describes DMA segments,
512  *                  number of segments,
513  *                  error code.
514  *
515  * This function is for the driver to receive mapping information resultant
516  * of the bus_dmamap_load(). The information is actually not being used, 
517  * but the address is saved anyway. 
518  */
519 static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
520         int nsegs, int error)
521 {
522     bus_addr_t *addr;
523
524     addr = arg;
525     *addr = segs[0].ds_addr;
526 }
527
528 /**
529  * mrsas_free_frames:    Frees memory for  MFI frames
530  * input:                Adapter soft state
531  *
532  * Deallocates MFI frames memory.  Called from mrsas_free_mem() during 
533  * detach and error case during creation of frame pool.
534  */
535 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
536 {
537     if (cmd->frame_phys_addr)
538         bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
539     if (cmd->frame_mem != NULL)
540         bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);
541 }