vmod/vmodttl: fixed bug related to luns not ordered and/or not starting from zero.
[ht-drivers.git] / utils / driver / drvr_utils.c
blob79dc9c6b25244e67495faeea97bf743515b69b5c
1 /**
2 * @file drvr_utils.c
4 * @brief Handy driver utils && functions.
6 * @author Yury Georgievskiy. CERN AB/CO.
8 * @date June, 2008
10 * @version 1.0 ygeorgie 03/06/2008 Creation date.
12 #include <linux/list.h> /* for list */
13 #include <linux/slab.h> /* for kmalloc && co. */
15 #include <data_tables.h> /* for 'bar_map_t' */
16 #include <general_both.h>
17 #include <general_drvr.h>
19 #if 0
20 struct module_descr *create_md_from()
23 #endif
26 /**
27 * map_bars - Resource allocation for device I/O Memory and I/O Port.
28 * Maps physical address of PCI buffer to virtual kernel space.
30 * @param l_head: List that will hold mapped BARs
31 * @param pdev: Pci device description
32 * @param bars: Bitmask of BARs to be requested
33 * @param name: Desired memory region name suffix(or NULL if none)
35 * @note Linked list should be freed afterwards by unmap_bars!
37 * @return how many BARs were mapped - in case of success.
38 * @return -EBUSY - in case of failure.
40 int map_bars(struct list_head *l_head, struct pci_dev *pdev, int bars, char *name)
42 char res_name[32] = "BAR";
43 bar_map_t *mem = NULL;
44 bar_map_t *memP, *tmpP;
45 int i, bcntr = 0;
46 void __iomem *ioaddr;
48 INIT_LIST_HEAD(l_head);
50 for (i = 0; i < 6; i++)
51 if ( (bars & (1 << i)) && (pci_resource_len(pdev, i)) ) {
52 memset(&res_name[3], 0, sizeof(res_name)-3);
53 snprintf(&res_name[3], sizeof(res_name)-3, "%d_%s", i, (name)?:'\0');
54 if (pci_request_region(pdev, i, res_name))
55 goto err_out;
56 /* we will treat I/O ports as if they were I/O memory */
57 if ( !(ioaddr = pci_iomap(pdev, i, 0)) )
58 goto err_out_iomap;
59 if ( !(mem = kzalloc((sizeof *mem), GFP_KERNEL)) )
60 goto err_out_alloc;
61 mem->mem_bar = i;
62 mem->mem_pdev = pdev;
63 mem->mem_remap = ioaddr;
64 mem->mem_len = pci_resource_len(pdev, i);
65 list_add_tail(&mem->mem_list/*new*/, l_head/*head*/);
66 ++bcntr;
68 return(bcntr);
70 err_out_alloc:
71 pci_iounmap(pdev, ioaddr);
72 err_out_iomap:
73 pci_release_region(pdev, i);
74 err_out:
75 /* free allocated resourses */
76 list_for_each_entry_safe(memP, tmpP, l_head, mem_list) {
77 pci_iounmap(memP->mem_pdev, memP->mem_remap);
78 pci_release_region(memP->mem_pdev, memP->mem_bar);
79 list_del(&memP->mem_list);
80 kfree(memP);
82 return(-EBUSY);
86 /**
87 * unmap_bars - Free resources, previously mapped by map_bars
89 * @param l_head: List that will hold mapped BARs.
90 * @param bars: Bitmask of BARs to be released
92 * @return number of BARs freed.
94 int unmap_bars(struct list_head *l_head, int bars)
96 bar_map_t *pos, *tmp;
97 int i;
98 int cc = 0;
100 for (i = 0; i < 6; i++)
101 if (bars & (1 << i)) { /* search for this BAR in the list */
102 list_for_each_entry_safe(pos, tmp, l_head, mem_list) {
103 if (pos->mem_bar == i) { /* bingo */
104 pci_iounmap(pos->mem_pdev, pos->mem_remap);
105 pci_release_region(pos->mem_pdev, pos->mem_bar);
106 list_del(&pos->mem_list); /* exclude from the list */
107 kfree(pos); /* free memory */
108 ++cc;
113 return(cc);
118 * get_bar_descr -
120 * @param l_head: list head with BAR description
121 * @param bar: BAR number [0 - 5] to search for
123 * @return BAR data pointer - if success.
124 * @return NULL - requested BAR not found.
126 inline bar_map_t* get_bar_descr(struct list_head *l_head, int bar)
128 bar_map_t *ptr;
130 list_for_each_entry(ptr, l_head, mem_list)
131 if (ptr->mem_bar == bar)
132 return(ptr);
134 return(NULL);
138 //!<
141 @todo SHOULD WE CONVERT FROM PCI LITTLE ENDIAN TO CPU ENDIANITY???\n
142 Or keep the data as it's comming from the device???
144 #define CONVERT_TO_CPU
146 #ifdef CONVERT_TO_CPU
147 #define _CTC(x) x
148 #else
149 #define _CTC(x)
150 #endif
153 /*! @name Generic I/O Memory access functions.
155 //@{
156 static inline
157 u16 genpci_read8(bar_map_t *bm, u8 offset)
159 return(ioread8(bm->mem_remap + offset));
162 static inline
163 void genpci_write8(bar_map_t *bm, u8 offset, u8 value)
165 iowrite8(value, bm->mem_remap + offset);
168 static inline
169 u16 genpci_read16(bar_map_t *bm, u16 offset)
171 return(_CTC(be16_to_cpu)(ioread16(bm->mem_remap + offset)));
174 static inline
175 void genpci_write16(bar_map_t *bm, u16 offset, u16 value)
177 iowrite16(_CTC(cpu_to_le16)(value), bm->mem_remap + offset);
180 static inline
181 u32 genpci_read32(bar_map_t *bm, u32 offset)
183 return(_CTC(be32_to_cpu)(ioread32(bm->mem_remap + offset)));
186 static inline
187 void genpci_write32(bar_map_t *bm, u32 offset, u32 value)
189 iowrite32(_CTC(cpu_to_le32)(value), bm->mem_remap + offset);
191 //@}
194 /*! @name Read register with shifting.
196 * Memory-Mapped I/O INSert [Byte, Word or Long SHIFT]
198 //@{
201 * _mmio_insb_shift - Read I/O memory in bytes (8bit) with shifting.
203 * @param addr:
204 * @param dst:
205 * @param count:
207 * <long-description>
210 inline void _mmio_insb_shift(void __iomem *addr, u8 *dst, int count)
212 while (--count >= 0) {
213 u8 data = __raw_readb(addr);
214 *dst = data;
215 ++dst;
216 addr += sizeof(*dst);
222 * _mmio_insw_shift - Read I/O memory in words (16bit) with shifting.
224 * @param addr:
225 * @param dst:
226 * @param count:
228 * <long-description>
231 inline void _mmio_insw_shift(void __iomem *addr, u16 *dst, int count)
233 while (--count >= 0) {
234 u16 data = __raw_readw(addr);
235 *dst = data;
236 ++dst;
237 addr += sizeof(*dst);
243 * _mmio_insl_shift - Read I/O memory in lwords (32bit) with shifting.
245 * @param addr: io memory address
246 * @param dst: data goes here
247 * @param count: how many lwords to read
249 * Copy data from io space to driver space lword by lword
252 inline void _mmio_insl_shift(void __iomem *addr, u32 *dst, int count)
254 //static int constdata = 0;
255 //int cntr = 0;
256 //u16 *ptr;
257 while (--count >= 0) {
258 //u32 __data = __raw_readl(addr);
259 //*dst = __data;
260 *dst = __raw_readl(addr);
261 //ptr = (u16*)dst;
262 //if (constdata) {
263 //printk("data[%02d] -> %#x u16[0] -> %#hx u16[1] -> %#hx\n", cntr, *dst, ptr[0], ptr[1]);
264 // cntr++;
265 // }
266 //constdata++;
267 //*dst = ioread32((unsigned long __iomem*)addr);
268 ++dst;
269 addr += sizeof(*dst);
272 //@}
275 /*! @name Write I/O register with shifting.
278 //@{
279 inline void _mmio_outsb_shift(void __iomem *addr, const u8 *src, int count)
281 while (--count >= 0) {
282 __raw_writeb(*src, addr);
283 src++;
284 addr += sizeof(*src);
288 inline void _mmio_outsw_shift(void __iomem *addr, const u16 *src, int count)
290 while (--count >= 0) {
291 __raw_writew(*src, addr);
292 src++;
293 addr += sizeof(*src);
297 inline void _mmio_outsl_shift(void __iomem *addr, const u32 *src, int count)
299 while (--count >= 0) {
300 __raw_writel(*src, addr);
301 src++;
302 addr += sizeof(*src);
305 //@}
309 * bar_read - read BARs
311 * @param bptr: BAR data
312 * @param bdata: user data
314 * To read device mapped BAR
317 inline void bar_read(bar_map_t* bptr, bar_rdwr_t *bdata)
319 /* as PCI operates in LE - we ?should? convert data to CPU */
320 switch (bdata->bar_utype) {
321 case 1:
322 bdata->bar_data.cval = genpci_read8(bptr, bdata->bar_offst);
323 //bdata->bar_data.cval = ioread8(bptr->mem_remap + bdata->bar_offst);
324 break;
325 case 2:
326 bdata->bar_data.sval = genpci_read16(bptr, bdata->bar_offst);
327 //bdata->bar_data.sval = ioread16(bptr->mem_remap + bdata->bar_offst);
328 break;
329 default:
330 bdata->bar_data.ival = le32_to_cpu(genpci_read32(bptr, bdata->bar_offst));
331 //bdata->bar_data.ival = ioread32(bptr->mem_remap + bdata->bar_offst);
332 break;
338 * bar_write - write BAR
340 * @param bptr: BAR data
341 * @param bdata: user data
343 * To write device mapped BAR.
346 inline void bar_write(bar_map_t* bptr, bar_rdwr_t *bdata)
348 switch (bdata->bar_utype) {
349 case 1:
350 genpci_write8(bptr, bdata->bar_offst, bdata->bar_data.cval);
351 //iowrite8(bdata->bar_data.cval, bptr->mem_remap + (u8)bdata->bar_offst);
352 break;
353 case 2:
354 genpci_write16(bptr, bdata->bar_offst, bdata->bar_data.sval);
355 //iowrite16(bdata->bar_data.sval, bptr->mem_remap + (u16)bdata->bar_offst);
356 break;
357 default:
358 genpci_write32(bptr, bdata->bar_offst, bdata->bar_data.ival);
359 //iowrite32(bdata->bar_data.ival, bptr->mem_remap + (u32)bdata->bar_offst);
360 break;