例: cat /proc/pci : Non-prefetchable 32 bit memory at 0xec001000. Bus 0, device 15, function 0: Bridge: Unknown vendor Unknown device (rev 1). Vendor id=136c. Device id=9054. Medium devsel. Fast back-to-back capable. IRQ 10. Non-prefetchable 32 bit memory at 0xec002000. I/O at 0x1400. I/O at 0x14f0. Bus 0, device 14, function 0: Multimedia video controller: Intel SAA7116 (rev 0). :この Vendor id=136c. Device id=9054 のボードは aPCI-P54 を増設した 際にあらわれるので aPCI-P54 の情報と容易に推測できる. 説明書によると 16バイトの I/Oポート のみを使用するはずであるが, ここでは メモリ領域一つとI/Oポート領域2つが確保されている. 実際に読み取り等を 行うと 14f0 からの領域がマニュアルにある領域であることが確認できる. 残り二つはなんであるかということになるが, アドテックシステム サイエンス社に問い合わせし確認したところ, ボード上の PCI-LocalBus変換用のICの管理領域とのご解答を頂いている.
static int ml_raw_read(struct inode * inode, struct file * file, char * buf, int count) { unsigned long p = file->f_pos; if(count>ML_SIZE-p) count=ML_SIZE-p; p+=ML_BASE; r=count; outb(MINOR(inode->i_rdev),ML_IO+1); memcpy_tofs(buf, (void *) p, count); file->f_pos += count; return count; } static int ml_raw_write(struct inode * inode, struct file * file, const char * buf,int count) { unsigned long p = file->f_pos; if(count>ML_SIZE-p) count=ML_SIZE-p; outb(MINOR(inode->i_rdev),ML_IO+1); p+=ML_BASE; memcpy_fromfs((void *) p, buf, count); file->f_pos += count; return count; } static int ml_raw_lseek(struct inode * inode, struct file * file, off_t offset, int orig) { switch (orig) { case 0: if((offset<0)||(offset>=ML_SIZE)) return -EINVAL; file->f_pos = offset; return file->f_pos; case 1: if((file->f_pos+offset<0)||(file->f_pos+offset>=ML_SIZE)) return -EINVAL; file->f_pos += offset; return file->f_pos; case 2: offset+=ML_SIZE; if((offset<0)||(offset>=ML_SIZE)) return -EINVAL; file->f_pos = offset; return file->f_pos; default: return -EINVAL; } return file->f_pos; }
実際のコードは /usr/src/linux/include/asm/segment.h内の __generic_memcpy_tofs()に 書かれている. movs 系列のストリング命令は ds:si->es:diに転送するため, 最初にスタック経由でfsをesにコピーしているのが確認できる (memcpy_fromfs では fs という命令によって ds のかわりに fs を使用).