4 * @brief Handy driver utils && functions.
6 * @author Yury Georgievskiy. CERN AB/CO.
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>
20 struct module_descr
*create_md_from()
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
;
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
))
56 /* we will treat I/O ports as if they were I/O memory */
57 if ( !(ioaddr
= pci_iomap(pdev
, i
, 0)) )
59 if ( !(mem
= kzalloc((sizeof *mem
), GFP_KERNEL
)) )
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*/);
71 pci_iounmap(pdev
, ioaddr
);
73 pci_release_region(pdev
, i
);
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
);
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
)
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 */
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
)
130 list_for_each_entry(ptr
, l_head
, mem_list
)
131 if (ptr
->mem_bar
== bar
)
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
153 /*! @name Generic I/O Memory access functions.
157 u16
genpci_read8(bar_map_t
*bm
, u8 offset
)
159 return(ioread8(bm
->mem_remap
+ offset
));
163 void genpci_write8(bar_map_t
*bm
, u8 offset
, u8 value
)
165 iowrite8(value
, bm
->mem_remap
+ offset
);
169 u16
genpci_read16(bar_map_t
*bm
, u16 offset
)
171 return(_CTC(be16_to_cpu
)(ioread16(bm
->mem_remap
+ offset
)));
175 void genpci_write16(bar_map_t
*bm
, u16 offset
, u16 value
)
177 iowrite16(_CTC(cpu_to_le16
)(value
), bm
->mem_remap
+ offset
);
181 u32
genpci_read32(bar_map_t
*bm
, u32 offset
)
183 return(_CTC(be32_to_cpu
)(ioread32(bm
->mem_remap
+ offset
)));
187 void genpci_write32(bar_map_t
*bm
, u32 offset
, u32 value
)
189 iowrite32(_CTC(cpu_to_le32
)(value
), bm
->mem_remap
+ offset
);
194 /*! @name Read register with shifting.
196 * Memory-Mapped I/O INSert [Byte, Word or Long SHIFT]
201 * _mmio_insb_shift - Read I/O memory in bytes (8bit) with shifting.
210 inline void _mmio_insb_shift(void __iomem
*addr
, u8
*dst
, int count
)
212 while (--count
>= 0) {
213 u8 data
= __raw_readb(addr
);
216 addr
+= sizeof(*dst
);
222 * _mmio_insw_shift - Read I/O memory in words (16bit) with shifting.
231 inline void _mmio_insw_shift(void __iomem
*addr
, u16
*dst
, int count
)
233 while (--count
>= 0) {
234 u16 data
= __raw_readw(addr
);
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;
257 while (--count
>= 0) {
258 //u32 __data = __raw_readl(addr);
260 *dst
= __raw_readl(addr
);
263 //printk("data[%02d] -> %#x u16[0] -> %#hx u16[1] -> %#hx\n", cntr, *dst, ptr[0], ptr[1]);
267 //*dst = ioread32((unsigned long __iomem*)addr);
269 addr
+= sizeof(*dst
);
275 /*! @name Write I/O register with shifting.
279 inline void _mmio_outsb_shift(void __iomem
*addr
, const u8
*src
, int count
)
281 while (--count
>= 0) {
282 __raw_writeb(*src
, addr
);
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
);
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
);
302 addr
+= sizeof(*src
);
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
) {
322 bdata
->bar_data
.cval
= genpci_read8(bptr
, bdata
->bar_offst
);
323 //bdata->bar_data.cval = ioread8(bptr->mem_remap + bdata->bar_offst);
326 bdata
->bar_data
.sval
= genpci_read16(bptr
, bdata
->bar_offst
);
327 //bdata->bar_data.sval = ioread16(bptr->mem_remap + bdata->bar_offst);
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);
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
) {
350 genpci_write8(bptr
, bdata
->bar_offst
, bdata
->bar_data
.cval
);
351 //iowrite8(bdata->bar_data.cval, bptr->mem_remap + (u8)bdata->bar_offst);
354 genpci_write16(bptr
, bdata
->bar_offst
, bdata
->bar_data
.sval
);
355 //iowrite16(bdata->bar_data.sval, bptr->mem_remap + (u16)bdata->bar_offst);
358 genpci_write32(bptr
, bdata
->bar_offst
, bdata
->bar_data
.ival
);
359 //iowrite32(bdata->bar_data.ival, bptr->mem_remap + (u32)bdata->bar_offst);