在移植linux到龙芯3210的过程中,调试串口的时候,遇到了一个outb函数,却找不到这个函数的原型。当时是用VIM的跳转功能来看的代码。直接用grep工具也找不到这个函数。后问人才发现其实outb实则上是一个宏函数,而这宏函数的写法还真是少见,可能是见识少了。
在./include/asm/io.h(其实asm是一个软链接,实际上是./include/asm-mips/io.h)中:
363 #define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, p, slow) /
364 /
365 static inline void pfx##out##bwlq##p(type val, unsigned long port) /
366 { /
367 volatile type *__addr; /
368 type __val; /
369 /
370 __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); /
371 /
372 __val = pfx##ioswab##bwlq(__addr, val); /
373 /
374 /* Really, we want this to be atomic */ /
375 BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); /
376 /
377 *__addr = __val; /
378 slow; /
379 }
411 #define __BUILD_IOPORT_PFX(bus, bwlq, type) /
412 __BUILD_IOPORT_SINGLE(bus, bwlq, type, ,) /
413 __BUILD_IOPORT_SINGLE(bus, bwlq, type, _p, SLOW_DOWN_IO)
414
415 #define BUILDIO_IOPORT(bwlq, type) /
416 __BUILD_IOPORT_PFX(, bwlq, type) /
417 __BUILD_IOPORT_PFX(__mem_, bwlq, type)
418
419 BUILDIO_IOPORT(b, u8)
420 BUILDIO_IOPORT(w, u16)
421 BUILDIO_IOPORT(l, u32)
从上面的代码看来,除了“##”比较难理解,其它都行。关键也是在“##”。经查资料,了解到这两个#的作用是连接字符串的作用。
从419行看来,传入的参数只有两个b,u8,那么只有两个参数,其它的字符串为空。
则看365行,明显得到:
pxf 为空字符串
bwlq = b
type = u8
那么得到两个函数:
static inline void outb(u8 val, unsigned long port)
{
... ....
}
static inline void outb_p(u8 val, unsigned long port)
{
... ....
SLOW_DOWN_IO;
}
89 #define __SLOW_DOWN_IO /
90 __asm__ __volatile__( /
91 "sb/t$0,0x80(%0)" /
92 : : "r" (mips_io_port_base));