This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / scsi / lpfc / lpfc_mbox.c
1 /*******************************************************************
2  * This file is part of the Emulex Linux Device Driver for         *
3  * Enterprise Fibre Channel Host Bus Adapters.                     *
4  * Refer to the README file included with this package for         *
5  * driver version and adapter support.                             *
6  * Copyright (C) 2004 Emulex Corporation.                          *
7  * www.emulex.com                                                  *
8  *                                                                 *
9  * This program is free software; you can redistribute it and/or   *
10  * modify it under the terms of the GNU General Public License     *
11  * as published by the Free Software Foundation; either version 2  *
12  * of the License, or (at your option) any later version.          *
13  *                                                                 *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of  *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *
17  * GNU General Public License for more details, a copy of which    *
18  * can be found in the file COPYING included with this package.    *
19  *******************************************************************/
20
21 /*
22  * $Id: lpfc_mbox.c 1.70 2004/11/18 17:33:04EST sf_support Exp  $
23  */
24 #include <linux/version.h>
25 #include <linux/blkdev.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/pci.h>
28 #include <linux/spinlock.h>
29 #include <scsi/scsi_device.h>
30 #include "lpfc_sli.h"
31 #include "lpfc_disc.h"
32 #include "lpfc_scsi.h"
33 #include "lpfc.h"
34 #include "lpfc_crtn.h"
35 #include "lpfc_hw.h"
36 #include "lpfc_logmsg.h"
37 #include "lpfc_mem.h"
38 #include "lpfc_compat.h"
39
40 /**********************************************/
41
42 /*                mailbox command             */
43 /**********************************************/
44 void
45 lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
46 {
47         MAILBOX_t *mb;
48
49         mb = &pmb->mb;
50         /* Setup to dump VPD region */
51         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
52         mb->mbxCommand = MBX_DUMP_MEMORY;
53         mb->un.varDmp.cv = 1;
54         mb->un.varDmp.type = DMP_NV_PARAMS;
55         mb->un.varDmp.region_id = DMP_REGION_VPD;
56         mb->un.varDmp.word_cnt = (DMP_VPD_SIZE / sizeof (uint32_t));
57
58         mb->un.varDmp.co = 0;
59         mb->un.varDmp.resp_offset = 0;
60         mb->mbxOwner = OWN_HOST;
61         return;
62 }
63
64 /**********************************************/
65 /*  lpfc_read_nv  Issue a READ NVPARAM        */
66 /*                mailbox command             */
67 /**********************************************/
68 void
69 lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
70 {
71         MAILBOX_t *mb;
72
73         mb = &pmb->mb;
74         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
75         mb->mbxCommand = MBX_READ_NV;
76         mb->mbxOwner = OWN_HOST;
77         return;
78 }
79
80 /**********************************************/
81 /*  lpfc_read_la  Issue a READ LA             */
82 /*                mailbox command             */
83 /**********************************************/
84 int
85 lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
86 {
87         MAILBOX_t *mb;
88         struct lpfc_dmabuf *mp;
89         struct lpfc_sli *psli;
90
91         psli = &phba->sli;
92         mb = &pmb->mb;
93         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
94
95         /* Get a buffer to hold the loop map */
96         if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_ATOMIC)) == 0) ||
97             ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) {
98                 if (mp)
99                         kfree(mp);
100                 mb->mbxCommand = MBX_READ_LA64;
101                 /* READ_LA: no buffers */
102                 lpfc_printf_log(phba,
103                                KERN_WARNING,
104                                LOG_MBOX,
105                                "%d:0300 READ_LA: no buffers\n",
106                                phba->brd_no);
107                 return (1);
108         }
109         INIT_LIST_HEAD(&mp->list);
110         mb->mbxCommand = MBX_READ_LA64;
111         mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
112         mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys);
113         mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys);
114
115         /* Sync the mailbox data with its PCI memory address now. */
116         pci_dma_sync_single_for_device(phba->pcidev, mp->phys, LPFC_BPL_SIZE,
117                         PCI_DMA_TODEVICE);
118
119         /* Save address for later completion and set the owner to host so that
120          * the FW knows this mailbox is available for processing.
121          */
122         pmb->context1 = (uint8_t *) mp;
123         mb->mbxOwner = OWN_HOST;
124         return (0);
125 }
126
127 /**********************************************/
128 /*  lpfc_clear_la  Issue a CLEAR LA           */
129 /*                 mailbox command            */
130 /**********************************************/
131 void
132 lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
133 {
134         MAILBOX_t *mb;
135
136         mb = &pmb->mb;
137         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
138
139         mb->un.varClearLA.eventTag = phba->fc_eventTag;
140         mb->mbxCommand = MBX_CLEAR_LA;
141         mb->mbxOwner = OWN_HOST;
142         return;
143 }
144
145 /**************************************************/
146 /*  lpfc_config_link  Issue a CONFIG LINK         */
147 /*                    mailbox command             */
148 /**************************************************/
149 void
150 lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
151 {
152         MAILBOX_t *mb = &pmb->mb;
153         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
154
155         /* NEW_FEATURE
156          * SLI-2, Coalescing Response Feature.
157          */
158         if (phba->cfg_cr_delay) {
159                 mb->un.varCfgLnk.cr = 1;
160                 mb->un.varCfgLnk.ci = 1;
161                 mb->un.varCfgLnk.cr_delay = phba->cfg_cr_delay;
162                 mb->un.varCfgLnk.cr_count = phba->cfg_cr_count;
163         }
164
165         mb->un.varCfgLnk.myId = phba->fc_myDID;
166         mb->un.varCfgLnk.edtov = phba->fc_edtov;
167         mb->un.varCfgLnk.arbtov = phba->fc_arbtov;
168         mb->un.varCfgLnk.ratov = phba->fc_ratov;
169         mb->un.varCfgLnk.rttov = phba->fc_rttov;
170         mb->un.varCfgLnk.altov = phba->fc_altov;
171         mb->un.varCfgLnk.crtov = phba->fc_crtov;
172         mb->un.varCfgLnk.citov = phba->fc_citov;
173
174         if (phba->cfg_ack0)
175                 mb->un.varCfgLnk.ack0_enable = 1;
176
177         mb->mbxCommand = MBX_CONFIG_LINK;
178         mb->mbxOwner = OWN_HOST;
179         return;
180 }
181
182 /**********************************************/
183 /*  lpfc_init_link  Issue an INIT LINK        */
184 /*                  mailbox command           */
185 /**********************************************/
186 void
187 lpfc_init_link(struct lpfc_hba * phba,
188                LPFC_MBOXQ_t * pmb, uint32_t topology, uint32_t linkspeed)
189 {
190         lpfc_vpd_t *vpd;
191         struct lpfc_sli *psli;
192         MAILBOX_t *mb;
193
194         mb = &pmb->mb;
195         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
196
197         psli = &phba->sli;
198         switch (topology) {
199         case FLAGS_TOPOLOGY_MODE_LOOP_PT:
200                 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
201                 mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
202                 break;
203         case FLAGS_TOPOLOGY_MODE_PT_PT:
204                 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
205                 break;
206         case FLAGS_TOPOLOGY_MODE_LOOP:
207                 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
208                 break;
209         case FLAGS_TOPOLOGY_MODE_PT_LOOP:
210                 mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
211                 mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
212                 break;
213         }
214
215         /* NEW_FEATURE
216          * Setting up the link speed
217          */
218         vpd = &phba->vpd;
219         if (vpd->rev.feaLevelHigh >= 0x02){
220                 switch(linkspeed){
221                         case LINK_SPEED_1G:
222                         case LINK_SPEED_2G:
223                         case LINK_SPEED_4G:
224                                 mb->un.varInitLnk.link_flags |= 
225                                                         FLAGS_LINK_SPEED;
226                                 mb->un.varInitLnk.link_speed = linkspeed;
227                         break;
228                         case LINK_SPEED_AUTO:
229                         default:
230                                 mb->un.varInitLnk.link_speed = 
231                                                         LINK_SPEED_AUTO;
232                         break;
233                 }
234                 
235         }
236         else
237                 mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO;
238
239         mb->mbxCommand = (volatile uint8_t)MBX_INIT_LINK;
240         mb->mbxOwner = OWN_HOST;
241         mb->un.varInitLnk.fabric_AL_PA = phba->fc_pref_ALPA;
242         return;
243 }
244
245 /**********************************************/
246 /*  lpfc_read_sparam  Issue a READ SPARAM     */
247 /*                    mailbox command         */
248 /**********************************************/
249 int
250 lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
251 {
252         struct lpfc_dmabuf *mp;
253         MAILBOX_t *mb;
254         struct lpfc_sli *psli;
255
256         psli = &phba->sli;
257         mb = &pmb->mb;
258         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
259
260         mb->mbxOwner = OWN_HOST;
261
262         /* Get a buffer to hold the HBAs Service Parameters */
263
264         if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_ATOMIC)) == 0) ||
265             ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) {
266                 if (mp)
267                         kfree(mp);
268                 mb->mbxCommand = MBX_READ_SPARM64;
269                 /* READ_SPARAM: no buffers */
270                 lpfc_printf_log(phba,
271                                 KERN_WARNING,
272                                 LOG_MBOX,
273                                 "%d:0301 READ_SPARAM: no buffers\n",
274                                 phba->brd_no);
275                 return (1);
276         }
277         INIT_LIST_HEAD(&mp->list);
278         mb->mbxCommand = MBX_READ_SPARM64;
279         mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
280         mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
281         mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys);
282
283         pci_dma_sync_single_for_device(phba->pcidev, mp->phys, LPFC_BPL_SIZE,
284                         PCI_DMA_TODEVICE);
285
286         /* save address for completion */
287         pmb->context1 = mp;
288
289         return (0);
290 }
291
292 /********************************************/
293 /*  lpfc_unreg_did  Issue a UNREG_DID       */
294 /*                  mailbox command         */
295 /********************************************/
296 void
297 lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
298 {
299         MAILBOX_t *mb;
300
301         mb = &pmb->mb;
302         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
303
304         mb->un.varUnregDID.did = did;
305
306         mb->mbxCommand = MBX_UNREG_D_ID;
307         mb->mbxOwner = OWN_HOST;
308         return;
309 }
310
311 /***********************************************/
312
313 /*                  command to write slim      */
314 /***********************************************/
315 void
316 lpfc_set_slim(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint32_t addr,
317               uint32_t value)
318 {
319         MAILBOX_t *mb;
320
321         mb = &pmb->mb;
322         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
323
324         /* addr = 0x090597 is AUTO ABTS disable for ELS commands */
325         /* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
326
327         /*
328          * Always turn on DELAYED ABTS for ELS timeouts
329          */
330         if ((addr == 0x052198) && (value == 0))
331                 value = 1;
332
333         mb->un.varWords[0] = addr;
334         mb->un.varWords[1] = value;
335
336         mb->mbxCommand = MBX_SET_SLIM;
337         mb->mbxOwner = OWN_HOST;
338         return;
339 }
340
341 /**********************************************/
342 /*  lpfc_read_nv  Issue a READ CONFIG         */
343 /*                mailbox command             */
344 /**********************************************/
345 void
346 lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
347 {
348         MAILBOX_t *mb;
349
350         mb = &pmb->mb;
351         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
352
353         mb->mbxCommand = MBX_READ_CONFIG;
354         mb->mbxOwner = OWN_HOST;
355         return;
356 }
357
358 /********************************************/
359 /*  lpfc_reg_login  Issue a REG_LOGIN       */
360 /*                  mailbox command         */
361 /********************************************/
362 int
363 lpfc_reg_login(struct lpfc_hba * phba,
364                uint32_t did, uint8_t * param, LPFC_MBOXQ_t * pmb, uint32_t flag)
365 {
366         uint8_t *sparam;
367         struct lpfc_dmabuf *mp;
368         MAILBOX_t *mb;
369         struct lpfc_sli *psli;
370
371         psli = &phba->sli;
372         mb = &pmb->mb;
373         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
374
375         mb->un.varRegLogin.rpi = 0;
376         mb->un.varRegLogin.did = did;
377         mb->un.varWords[30] = flag;     /* Set flag to issue action on cmpl */
378
379         mb->mbxOwner = OWN_HOST;
380
381         /* Get a buffer to hold NPorts Service Parameters */
382         if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_ATOMIC)) == 0) ||
383             ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) {
384                 if (mp)
385                         kfree(mp);
386
387                 mb->mbxCommand = MBX_REG_LOGIN64;
388                 /* REG_LOGIN: no buffers */
389                 lpfc_printf_log(phba,
390                                KERN_WARNING,
391                                LOG_MBOX,
392                                "%d:0302 REG_LOGIN: no buffers Data x%x x%x\n",
393                                phba->brd_no,
394                                (uint32_t) did, (uint32_t) flag);
395                 return (1);
396         }
397         INIT_LIST_HEAD(&mp->list);
398         sparam = mp->virt;
399
400         /* Copy param's into a new buffer */
401         memcpy(sparam, param, sizeof (struct serv_parm));
402
403         /* Sync the mailbox data with its PCI memory address now. */
404         pci_dma_sync_single_for_device(phba->pcidev, mp->phys, LPFC_BPL_SIZE,
405                         PCI_DMA_TODEVICE);
406
407         /* save address for completion */
408         pmb->context1 = (uint8_t *) mp;
409
410         mb->mbxCommand = MBX_REG_LOGIN64;
411         mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
412         mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys);
413         mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys);
414
415         return (0);
416 }
417
418 /**********************************************/
419 /*  lpfc_unreg_login  Issue a UNREG_LOGIN     */
420 /*                    mailbox command         */
421 /**********************************************/
422 void
423 lpfc_unreg_login(struct lpfc_hba * phba, uint32_t rpi, LPFC_MBOXQ_t * pmb)
424 {
425         MAILBOX_t *mb;
426
427         mb = &pmb->mb;
428         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
429
430         mb->un.varUnregLogin.rpi = (uint16_t) rpi;
431         mb->un.varUnregLogin.rsvd1 = 0;
432
433         mb->mbxCommand = MBX_UNREG_LOGIN;
434         mb->mbxOwner = OWN_HOST;
435         return;
436 }
437
438 static void
439 lpfc_config_pcb_setup(struct lpfc_hba * phba)
440 {
441         struct lpfc_sli *psli = &phba->sli;
442         struct lpfc_sli_ring *pring;
443         PCB_t *pcbp = &phba->slim2p->pcb;
444         LPFC_RING_INIT_t *pringinit;
445         dma_addr_t pdma_addr;
446         uint32_t offset;
447         uint32_t iocbCnt;
448         int i;
449
450         psli->MBhostaddr = (uint32_t *)&phba->slim2p->mbx;
451         pcbp->maxRing = (psli->sliinit.num_rings - 1);
452
453         iocbCnt = 0;
454         for (i = 0; i < psli->sliinit.num_rings; i++) {
455                 pringinit = &psli->sliinit.ringinit[i];
456                 pring = &psli->ring[i];
457                 /* A ring MUST have both cmd and rsp entries defined to be
458                    valid */
459                 if ((pringinit->numCiocb == 0) || (pringinit->numRiocb == 0)) {
460                         pcbp->rdsc[i].cmdEntries = 0;
461                         pcbp->rdsc[i].rspEntries = 0;
462                         pcbp->rdsc[i].cmdAddrHigh = 0;
463                         pcbp->rdsc[i].rspAddrHigh = 0;
464                         pcbp->rdsc[i].cmdAddrLow = 0;
465                         pcbp->rdsc[i].rspAddrLow = 0;
466                         pring->cmdringaddr = NULL;
467                         pring->rspringaddr = NULL;
468                         continue;
469                 }
470                 /* Command ring setup for ring */
471                 pring->cmdringaddr =
472                     (void *)&phba->slim2p->IOCBs[iocbCnt];
473                 pcbp->rdsc[i].cmdEntries = pringinit->numCiocb;
474
475                 offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
476                          (uint8_t *)phba->slim2p;
477                 pdma_addr = phba->slim2p_mapping + offset;
478                 pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr);
479                 pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr);
480                 iocbCnt += pringinit->numCiocb;
481
482                 /* Response ring setup for ring */
483                 pring->rspringaddr =
484                     (void *)&phba->slim2p->IOCBs[iocbCnt];
485
486                 pcbp->rdsc[i].rspEntries = pringinit->numRiocb;
487                 offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
488                          (uint8_t *)phba->slim2p;
489                 pdma_addr = phba->slim2p_mapping + offset;
490                 pcbp->rdsc[i].rspAddrHigh = putPaddrHigh(pdma_addr);
491                 pcbp->rdsc[i].rspAddrLow = putPaddrLow(pdma_addr);
492                 iocbCnt += pringinit->numRiocb;
493         }
494 }
495
496 void
497 lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
498 {
499         MAILBOX_t *mb;
500
501         mb = &pmb->mb;
502         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
503         mb->un.varRdRev.cv = 1;
504         mb->mbxCommand = MBX_READ_REV;
505         mb->mbxOwner = OWN_HOST;
506         return;
507 }
508
509 void
510 lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
511 {
512         int i;
513         MAILBOX_t *mb = &pmb->mb;
514         struct lpfc_sli *psli;
515         LPFC_RING_INIT_t *pring;
516
517         memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
518
519         mb->un.varCfgRing.ring = ring;
520         mb->un.varCfgRing.maxOrigXchg = 0;
521         mb->un.varCfgRing.maxRespXchg = 0;
522         mb->un.varCfgRing.recvNotify = 1;
523
524         psli = &phba->sli;
525         pring = &psli->sliinit.ringinit[ring];
526         mb->un.varCfgRing.numMask = pring->num_mask;
527         mb->mbxCommand = MBX_CONFIG_RING;
528         mb->mbxOwner = OWN_HOST;
529
530         /* Is this ring configured for a specific profile */
531         if (pring->prt[0].profile) {
532                 mb->un.varCfgRing.profile = pring->prt[0].profile;
533                 return;
534         }
535
536         /* Otherwise we setup specific rctl / type masks for this ring */
537         for (i = 0; i < pring->num_mask; i++) {
538                 mb->un.varCfgRing.rrRegs[i].rval = pring->prt[i].rctl;
539                 if (mb->un.varCfgRing.rrRegs[i].rval != FC_ELS_REQ)
540                         mb->un.varCfgRing.rrRegs[i].rmask = 0xff;
541                 else
542                         mb->un.varCfgRing.rrRegs[i].rmask = 0xfe;
543                 mb->un.varCfgRing.rrRegs[i].tval = pring->prt[i].type;
544                 mb->un.varCfgRing.rrRegs[i].tmask = 0xff;
545         }
546
547         return;
548 }
549
550 void
551 lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
552 {
553         MAILBOX_t *mb = &pmb->mb;
554         dma_addr_t pdma_addr;
555         uint32_t bar_low, bar_high;
556         size_t offset;
557         HGP hgp;
558         void *to_slim;
559
560         memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
561         mb->mbxCommand = MBX_CONFIG_PORT;
562         mb->mbxOwner = OWN_HOST;
563
564         mb->un.varCfgPort.pcbLen = sizeof(PCB_t);
565         offset = (uint8_t *)&phba->slim2p->pcb - (uint8_t *)phba->slim2p;
566         pdma_addr = phba->slim2p_mapping + offset;
567         mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
568         mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
569
570         /* Now setup pcb */
571         phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
572         phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
573
574         /* Setup Mailbox pointers */
575         phba->slim2p->pcb.mailBoxSize = sizeof(MAILBOX_t);
576         offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
577         pdma_addr = phba->slim2p_mapping + offset;
578         phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
579         phba->slim2p->pcb.mbAddrLow = putPaddrLow(pdma_addr);
580
581         /*
582          * Setup Host Group ring pointer.
583          *
584          * For efficiency reasons, the ring get/put pointers can be
585          * placed in adapter memory (SLIM) rather than in host memory.
586          * This allows firmware to avoid PCI reads/writes when updating
587          * and checking pointers.
588          *
589          * The firmware recognizes the use of SLIM memory by comparing
590          * the address of the get/put pointers structure with that of
591          * the SLIM BAR (BAR0).
592          *
593          * Caution: be sure to use the PCI config space value of BAR0/BAR1
594          * (the hardware's view of the base address), not the OS's
595          * value of pci_resource_start() as the OS value may be a cookie
596          * for ioremap/iomap.
597          */
598         
599
600         pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low);
601         pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high);
602
603
604         /* mask off BAR0's flag bits 0 - 3 */
605         phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
606                                         (SLIMOFF*sizeof(uint32_t));
607         if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
608                 phba->slim2p->pcb.hgpAddrHigh = bar_high;
609         else 
610                 phba->slim2p->pcb.hgpAddrHigh = 0;
611         /* write HGP data to SLIM at the required longword offset */
612         memset(&hgp, 0, sizeof(HGP));
613         to_slim = (uint8_t *)phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
614         lpfc_memcpy_to_slim(to_slim, &hgp, sizeof (HGP));
615
616         /* Setup Port Group ring pointer */
617         offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
618                  (uint8_t *)phba->slim2p;
619         pdma_addr = phba->slim2p_mapping + offset;
620         phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
621         phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
622
623         /* Use callback routine to setp rings in the pcb */
624         lpfc_config_pcb_setup(phba);
625
626         /* special handling for LC HBAs */
627         if (lpfc_is_LC_HBA(phba->pcidev->device)) {
628                 uint32_t hbainit[5];
629
630                 lpfc_hba_init(phba, hbainit);
631
632                 memcpy(&mb->un.varCfgPort.hbainit, hbainit, 20);
633         }
634
635         /* Swap PCB if needed */
636         lpfc_sli_pcimem_bcopy((uint32_t *)&phba->slim2p->pcb,
637                               (uint32_t *)&phba->slim2p->pcb,
638                               sizeof (PCB_t));
639
640         lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
641                         "%d:0405 Service Level Interface (SLI) 2 selected\n",
642                         phba->brd_no);
643 }
644
645 void
646 lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
647 {
648         struct lpfc_sli *psli;
649
650         psli = &phba->sli;
651
652         list_add_tail(&mbq->list, &psli->mboxq);
653
654         psli->mboxq_cnt++;
655
656         return;
657 }
658
659 LPFC_MBOXQ_t *
660 lpfc_mbox_get(struct lpfc_hba * phba)
661 {
662         LPFC_MBOXQ_t *mbq = NULL;
663         struct lpfc_sli *psli = &phba->sli;
664
665         if (!list_empty(&psli->mboxq)) {
666                 mbq = list_entry(psli->mboxq.next, LPFC_MBOXQ_t, list);
667                 list_del_init(&mbq->list);
668                 psli->mboxq_cnt--;
669         }
670
671         return mbq;
672 }