2 * Adaptec AAC series RAID controller driver
3 * (c) Copyright 2001 Red Hat Inc. <alan@redhat.com>
5 * based on the old aacraid driver that is..
6 * Adaptec aacraid device driver for Linux.
8 * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; see the file COPYING. If not, write to
22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 * Abstract: This supports the initialization of the host adapter commuication interface.
28 * This is a platform dependent module for the pci cyclone board.
32 #include <linux/kernel.h>
33 #include <linux/init.h>
34 #include <linux/types.h>
35 #include <linux/sched.h>
36 #include <linux/pci.h>
37 #include <linux/spinlock.h>
38 #include <linux/slab.h>
39 #include <linux/blkdev.h>
40 #include <linux/completion.h>
42 #include <asm/semaphore.h>
46 struct aac_common aac_config
;
48 static int aac_alloc_comm(struct aac_dev
*dev
, void **commaddr
, unsigned long commsize
, unsigned long commalign
)
51 unsigned long size
, align
;
52 unsigned long fibsize
= 4096;
53 unsigned long printfbufsiz
= 256;
54 struct aac_init
*init
;
57 size
= fibsize
+ sizeof(struct aac_init
) + commsize
+ commalign
+ printfbufsiz
;
60 base
= pci_alloc_consistent(dev
->pdev
, size
, &phys
);
64 printk(KERN_ERR
"aacraid: unable to create mapping.\n");
67 dev
->comm_addr
= (void *)base
;
68 dev
->comm_phys
= phys
;
69 dev
->comm_size
= size
;
71 dev
->init
= (struct aac_init
*)(base
+ fibsize
);
72 dev
->init_pa
= phys
+ fibsize
;
76 init
->InitStructRevision
= cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION
);
77 init
->MiniPortRevision
= cpu_to_le32(Sa_MINIPORT_REVISION
);
78 init
->fsrev
= cpu_to_le32(dev
->fsrev
);
81 * Adapter Fibs are the first thing allocated so that they
84 dev
->aif_base_va
= (struct hw_fib
*)base
;
86 init
->AdapterFibsVirtualAddress
= 0;
87 init
->AdapterFibsPhysicalAddress
= cpu_to_le32((u32
)phys
);
88 init
->AdapterFibsSize
= cpu_to_le32(fibsize
);
89 init
->AdapterFibAlign
= cpu_to_le32(sizeof(struct hw_fib
));
91 * number of 4k pages of host physical memory. The aacraid fw needs
92 * this number to be less than 4gb worth of pages. num_physpages is in
93 * system page units. New firmware doesn't have any issues with the
94 * mapping system, but older Firmware did, and had *troubles* dealing
95 * with the math overloading past 32 bits, thus we must limit this
98 * This assumes the memory is mapped zero->n, which isnt
99 * always true on real computers. It also has some slight problems
100 * with the GART on x86-64. I've btw never tried DMA from PCI space
101 * on this platform but don't be suprised if its problematic.
103 #ifndef CONFIG_GART_IOMMU
104 if ((num_physpages
<< (PAGE_SHIFT
- 12)) <= AAC_MAX_HOSTPHYSMEMPAGES
) {
105 init
->HostPhysMemPages
=
106 cpu_to_le32(num_physpages
<< (PAGE_SHIFT
-12));
110 init
->HostPhysMemPages
= cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES
);
115 * Increment the base address by the amount already used
117 base
= base
+ fibsize
+ sizeof(struct aac_init
);
118 phys
= (dma_addr_t
)((ulong
)phys
+ fibsize
+ sizeof(struct aac_init
));
120 * Align the beginning of Headers to commalign
122 align
= (commalign
- ((unsigned long)(base
) & (commalign
- 1)));
126 * Fill in addresses of the Comm Area Headers and Queues
129 init
->CommHeaderAddress
= cpu_to_le32((u32
)phys
);
131 * Increment the base address by the size of the CommArea
133 base
= base
+ commsize
;
134 phys
= phys
+ commsize
;
136 * Place the Printf buffer area after the Fast I/O comm area.
138 dev
->printfbuf
= (void *)base
;
139 init
->printfbuf
= cpu_to_le32(phys
);
140 init
->printfbufsiz
= cpu_to_le32(printfbufsiz
);
141 memset(base
, 0, printfbufsiz
);
145 static void aac_queue_init(struct aac_dev
* dev
, struct aac_queue
* q
, u32
*mem
, int qsize
)
149 INIT_LIST_HEAD(&q
->pendingq
);
150 init_waitqueue_head(&q
->cmdready
);
151 INIT_LIST_HEAD(&q
->cmdq
);
152 init_waitqueue_head(&q
->qfull
);
153 spin_lock_init(&q
->lockdata
);
154 q
->lock
= &q
->lockdata
;
155 q
->headers
.producer
= mem
;
156 q
->headers
.consumer
= mem
+1;
157 *(q
->headers
.producer
) = cpu_to_le32(qsize
);
158 *(q
->headers
.consumer
) = cpu_to_le32(qsize
);
163 * aac_send_shutdown - shutdown an adapter
164 * @dev: Adapter to shutdown
166 * This routine will send a VM_CloseAll (shutdown) request to the adapter.
169 int aac_send_shutdown(struct aac_dev
* dev
)
172 struct aac_close
*cmd
;
175 fibctx
= fib_alloc(dev
);
178 cmd
= (struct aac_close
*) fib_data(fibctx
);
180 cmd
->command
= cpu_to_le32(VM_CloseAll
);
181 cmd
->cid
= cpu_to_le32(0xffffffff);
183 status
= fib_send(ContainerCommand
,
185 sizeof(struct aac_close
),
191 fib_complete(fibctx
);
197 * aac_comm_init - Initialise FSA data structures
198 * @dev: Adapter to initialise
200 * Initializes the data structures that are required for the FSA commuication
201 * interface to operate.
203 * 1 - if we were able to init the commuication interface.
204 * 0 - If there were errors initing. This is a fatal error.
207 int aac_comm_init(struct aac_dev
* dev
)
209 unsigned long hdrsize
= (sizeof(u32
) * NUMBER_OF_COMM_QUEUES
) * 2;
210 unsigned long queuesize
= sizeof(struct aac_entry
) * TOTAL_QUEUE_ENTRIES
;
212 struct aac_entry
* queues
;
214 struct aac_queue_block
* comm
= dev
->queues
;
216 * Now allocate and initialize the zone structures used as our
217 * pool of FIB context records. The size of the zone is based
218 * on the system memory size. We also initialize the mutex used
219 * to protect the zone.
221 spin_lock_init(&dev
->fib_lock
);
224 * Allocate the physically contigous space for the commuication
228 size
= hdrsize
+ queuesize
;
230 if (!aac_alloc_comm(dev
, (void * *)&headers
, size
, QUEUE_ALIGNMENT
))
233 queues
= (struct aac_entry
*)(((ulong
)headers
) + hdrsize
);
235 /* Adapter to Host normal priority Command queue */
236 comm
->queue
[HostNormCmdQueue
].base
= queues
;
237 aac_queue_init(dev
, &comm
->queue
[HostNormCmdQueue
], headers
, HOST_NORM_CMD_ENTRIES
);
238 queues
+= HOST_NORM_CMD_ENTRIES
;
241 /* Adapter to Host high priority command queue */
242 comm
->queue
[HostHighCmdQueue
].base
= queues
;
243 aac_queue_init(dev
, &comm
->queue
[HostHighCmdQueue
], headers
, HOST_HIGH_CMD_ENTRIES
);
245 queues
+= HOST_HIGH_CMD_ENTRIES
;
248 /* Host to adapter normal priority command queue */
249 comm
->queue
[AdapNormCmdQueue
].base
= queues
;
250 aac_queue_init(dev
, &comm
->queue
[AdapNormCmdQueue
], headers
, ADAP_NORM_CMD_ENTRIES
);
252 queues
+= ADAP_NORM_CMD_ENTRIES
;
255 /* host to adapter high priority command queue */
256 comm
->queue
[AdapHighCmdQueue
].base
= queues
;
257 aac_queue_init(dev
, &comm
->queue
[AdapHighCmdQueue
], headers
, ADAP_HIGH_CMD_ENTRIES
);
259 queues
+= ADAP_HIGH_CMD_ENTRIES
;
262 /* adapter to host normal priority response queue */
263 comm
->queue
[HostNormRespQueue
].base
= queues
;
264 aac_queue_init(dev
, &comm
->queue
[HostNormRespQueue
], headers
, HOST_NORM_RESP_ENTRIES
);
265 queues
+= HOST_NORM_RESP_ENTRIES
;
268 /* adapter to host high priority response queue */
269 comm
->queue
[HostHighRespQueue
].base
= queues
;
270 aac_queue_init(dev
, &comm
->queue
[HostHighRespQueue
], headers
, HOST_HIGH_RESP_ENTRIES
);
272 queues
+= HOST_HIGH_RESP_ENTRIES
;
275 /* host to adapter normal priority response queue */
276 comm
->queue
[AdapNormRespQueue
].base
= queues
;
277 aac_queue_init(dev
, &comm
->queue
[AdapNormRespQueue
], headers
, ADAP_NORM_RESP_ENTRIES
);
279 queues
+= ADAP_NORM_RESP_ENTRIES
;
282 /* host to adapter high priority response queue */
283 comm
->queue
[AdapHighRespQueue
].base
= queues
;
284 aac_queue_init(dev
, &comm
->queue
[AdapHighRespQueue
], headers
, ADAP_HIGH_RESP_ENTRIES
);
286 comm
->queue
[AdapNormCmdQueue
].lock
= comm
->queue
[HostNormRespQueue
].lock
;
287 comm
->queue
[AdapHighCmdQueue
].lock
= comm
->queue
[HostHighRespQueue
].lock
;
288 comm
->queue
[AdapNormRespQueue
].lock
= comm
->queue
[HostNormCmdQueue
].lock
;
289 comm
->queue
[AdapHighRespQueue
].lock
= comm
->queue
[HostHighCmdQueue
].lock
;
294 struct aac_dev
*aac_init_adapter(struct aac_dev
*dev
)
297 * Ok now init the communication subsystem
300 dev
->queues
= (struct aac_queue_block
*) kmalloc(sizeof(struct aac_queue_block
), GFP_KERNEL
);
301 if (dev
->queues
== NULL
) {
302 printk(KERN_ERR
"Error could not allocate comm region.\n");
305 memset(dev
->queues
, 0, sizeof(struct aac_queue_block
));
307 if (aac_comm_init(dev
)<0){
312 * Initialize the list of fibs
314 if(fib_setup(dev
)<0){
319 INIT_LIST_HEAD(&dev
->fib_list
);
320 init_completion(&dev
->aif_completion
);