          Linux I/O |[gvO~O ~jnEc[

               : rjs@spider.compart.fi (Riku Saikkonen)
          ŏI : Aug 26 1996

                    : 쓇 _       (kei@sm.sony.co.jp)
          ̋ᖡ/Z : R NO (hiro@koneeko.linux.or.jp)

  ̃hLg̒쌠 1995-1996 Riku Saikkonsen ɑ܂B
  ڍׂɊւĂ͒ʏ Linux  HOWTO COPYRIGHT B

   nEc[ł́ACe x86 vZbTővÓA
  n[hEGA I/O |[g̃vO~OƁALinux ̃[U[hŒZ
  ҂ȂvOAȂǂɂďqׂ܂B

  ͑Oɂ悤(ƂĂ) IO-Port-mini-HOWTO ܂A
  ͂̑̕҂łB

  AȂɂԈႢAt邱ƂȂǂ܂為
  ɃCĂB(rjs@spider.compart.fi)...

  Õo[W (Dec 26 1995) ̕ύX_:
          * Q[|[g̃vO~OɊւ
          * C ȊǑ
          * nanosleep()
          * yeBAvZbT̃^C~O
          * R[fCOǉ
          * ̏ȏC
  ȂǂłB

          C vO I/O |[gg ... ʂ̕@

  I/O |[gANZX邽߂̃[`/usr/include/asm/io.h (܂
  J[l̃\[XpbP[W̒ linux/include/asm-i386/io.h)ɒ`
  ܂BKvȃ[`́A̒ŃCC}NƂĒ`Ă܂̂ŁA
          #include <asm/io.h>
  Ƃ邾ŏ\ł傤B
  ʂȃCuȂǂ͕svłB

  ̃[`g\[Xł́Agcc (ȂƂ 2.7.2 ܂͂
  Õo[W)gƂɁÂ悤Ȑ܂B

  œKIɂ(-O1 ܂͂ȏ)A
  łȂ asm/io.h CN[hO
          #define extern
  Ƃ̐錾ȂĂKv܂B

  fobÔ߂ɁAugcc -g -OvgƂł܂(ȂƂŋ߂
  gccł) AœKꂽR[hł̓fobKςȋƂ
  ܂B̂悤ȏꍇɂ́AI/O |[gANZX܂񂾃R[hƗ
  t@CɂĂāÃt@C̃RpC̎ɂœK
  IɂƂ@gƂł܂B

  |[gANZXOɁÃ|[gANZX鋖vOɗ^
  Ȃ΂Ȃ܂Bɂ́Aioperm(2) ֐(unistd.h Ő錾AJ[l
  ̒Œ`Ă)Ăяo܂B
  ̊֐̓vO̍ŏ̕ŌĂяoKv܂B(I/O |[gANZX
  O)
  ̊֐̏ ioperm(from, num, turn_on) łB
          from  ANZX|[g̍ŏ̃AhXB
          num ́Afrom 炢̘AAhX̃ANZXB
  w肵܂B
  Ⴆ΁Aioperm(0x300, 5, 1) ́A0x300  0x304 (v5̃|[g)
  ɑ΂鋖w肵AŌ̃p[^ł́Ã|[gɑ΂ANZX
  ^̂֎~̂_l(true : 1 = ^, false : 0 = 
  ֎~)Ŏw肵܂B
  AĂȂ|[g̏ꍇɂ́A ioperm() ĂяoāAK؂ȋ
  w肵܂B
  ioperm() ̏ڍׂȕ@ɊւĂ ioperm(2) ̃}jAy[WQƂĉB

  ioperm() Ăяoɂ́ÃvO root őĂ邱Ƃ
  KvłB܂ÃvO[g[UŎs邩AZbg UID
  root (: st@C̃I[i[ root ɂĂAchmod 4755 hogehoge Ƃ
  łB)ɂĂKv܂B

  Kvȃ|[gɑ΂鋖 ioperm() ŗ^ƂɁAroot 𗎂
  ł܂B
  vO̍ŌŁAz ioperm(..., 0) Ăяoċ𗎂Kv
  ܂B̓vȌIɎIɍsȂ܂B

  ioperm() Őݒ肵 I/O ɑ΂ANZX́Afork() Aexec() ʂ
  p܂B
  ܂Aroot ȊÕ[U setuid ɂp܂B

  ioperm() ł́A0x000  0x3ff ܂ł̃|[gɑ΂ANZX
  ^邱Ƃ͂ł܂B̃|[gɑ΂ẮAiopl(2) 
  gKv܂B(iopl(2) gƈxɂׂẴ|[gɑ΂
  ANZX^邱ƂɂȂ܂B)
  ׂẴ|[gɑ΂ăANZX^ɂ́Axp[^Ƃ
  u3vg܂B܂Auiopl(3);vƂ֐Ăяo܂B
  Aiopl() Ăяoɂ root KvłB

  āAۂɃ|[gANZXԂłB

  |[g͂ꍇɂinb(port); Ăяo܂B
  ͓̓|[gƂĂoCgf[^Ԃ܂B

  |[gɏo͂ɂ́Aoutb(value, port); Ăяo܂B
  (p[^̏ԂɒӂĉB)(:AZuAMS-DOS ̃RpC
  CuȂǂ̏ꍇƂ͋tłB)

  |[gAhX x  x+1 烏[hf[^͂ꍇɂ inw(x);
  Ăяo܂B(AZuINW Ƃ܂悤ɂꂼ̃|[g
  1oCgǂłāA[hf[^\킯ł)
  ӂ̃|[gɃ[h(2oCg)o͂ɂ outw(value, x); g܂B

  inb_p(), outb_p(), inw_p(), outw_p() Ƃ}ŃAɏqׂ̂
  ܂A|[gɃANZXɏ(1}CNb)
  EGCg܂B
  asm/io.h CN[hO REALLY_SLOW_IO  #define ƁA
  ̃EGCgԂ4}CNbɕς邱Ƃł܂B

  ̃}N͒ʏA0x80 Ԓn I/O |[gɏo͂邱ƂŃEGCg
  Ă܂B(#define SLOW_IO_BY_JUMPING Ăꍇɂ͕ʂ̕@
  g܂A͂܂萳mȒxȂƂłȂ͂łB)
  ̂悤ȗRA0x80 Ԓñ|[gɑ΂ ioperm()ɎsĂKv
  ܂B(0x80 Ԓñ|[gɑ΂o͂̓VXeɑ΂ĂȂe
  ^邱Ƃ͂Ȃ͂łB)
  ɂ܂܂ȒxsȂ@ɂẮAȉǂݐi߂ĉB

  ŋ߂̃[X man y[Wɂ́Ã}NɊւ܂B

  guV[eBO:

  Q1. |[gANZX segmentation faults NĂ܂܂B

  A1. vO root ĂȂAȂ炩̗R ioperm()
      ĂяoɎsĂ̂ł傤Bioperm() ̕Ԃl𒲂ׂĂ݂
      B

  Q2. in*() Ƃ out*() Ƃ̊֐ǂɂ݂܂Bgcc 
      undefined reference ƂĂ܂B

  A2. RpC̎ɍœKI (-O) ɂȂ̂ł? ̌ʁA
      gcc  asm/io.h ̒ɂ}N邱ƂłȂ̂łB
      ƂA#include <asm/io.h> YĂ܂?

  Q3. out*() sĂȂɂȂA܂͂Ȃ񂩕ςȂ̂łB

  A3. p[^̏Ԃ`FbNĉBoutb(value, port) Ƃ
      ԂłBMS-DOS łȂ݂ outportb(port,value) Ƃ͋tłB

          I/O |[gANZXʂ̕@

  ̕@́Aopen() g /dev/port (LN^foCXAW[
  ԍ 1A}Ci[ԍ4)I[vāAread/write ȂƂ@łB
  (stdio  f*()֐(: fwrite() Ƃ fread() Ƃ...)͓Ńobt@O
  Ă̂ŁAg܂ˁB)
  I[vɁAo͂|[g̃AhX܂ lseek() ܂B
  (file position 0  |[g 0 ɁAfile position 1  |[g 1 ... Ƃ
  ɑ܂B)
  ̌ read(), write() găoCg/[hǂݏ܂B

  ̕@gɂ́A ̃vO /dev/port ɑ΂ read/write
  ĂȂ΂Ȃ܂B
  ̕@͏ɏqׂʏ̕@炭xł傤A(RpC)
  œK ioperm() svłƂ_܂B

          荞 (IRQ)  DMA ANZX

  [U[h̃vO璼ڂɊ荞݂ DMA gƂ͂ł܂B
  ɂ́AJ[lhCo쐬Kv܂B̏ڍׂɂĂ
  uLinux J[lnbJ[Y KChvA܂̗ƂẮAJ[l
  \[XR[hǂŉB

  ܂A[U[hvO̒Ŋ荞݂֎~i܂B

          x̃^C~O: fBC

  ܂ŏɒfĂ܂A[UvOɂĐmȃ^C~Oۏ
  邱Ƃ͂ł܂B́ALinux }`^XNEvGveBu
  ȃVXełBȂ̃vZXA20mb琔b(ɕׂ
  VXeȂǂ)ɓnĂȂ炩̗RŃXPW[OΏۂ
  O邱Ƃ́Ał蓾܂B

  AI/O |[ggقƂǂ̃AvP[Vł́A͎ۂɂ
  ɂ͂ȂȂł傤B

  ̎Ԃł邾邽߂ɂ́Anice gāAvZX̗D揇
  ƂƂł܂B(: XbVOĂ悤ȏ
  ł nice ̌ʂ͂قƂǂȂƎv܂APɕׂ悤ȏꍇ
  (܂ACPU \[XȂAƂ)ɂ͌ʂ̂ȁB)

  Linux J[lɃA^C@\ǉƂv܂B
  ɂẮAhttp://luz.cs.nmt.edu/~rtlinux 䗗B

  āAƊȒPȃ^C~OɂĂb܂傤Bb̃fBC
  ~ꍇɂ́A炭 sleep(3) ł傤B\~bȏ
  fBC(ŏ̃fBC͖20~b̂悤łB)̏ꍇɂ usleep(3)
  E߂łB

  ̊֐ĂяoƁACPU ͑̃vZXɊ蓖Ă܂̂ŁA
  CPU ^CʂɂȂ邱Ƃ͂܂B
  ڍׂɂĂ man y[W䗗B

   20 ~bfBCɊւĂ(炭vZbT}V
  xAVXeׂ̕ɂˑ܂)Aɏqׂ悤 CPU Ă܂
  ƂAv[`ł͂܂܂BʏALinux ̃XPW[Ȃ
  vZXɑ΂Đ߂OɏȂƂ 20 ~b͂邩łB

  ̗RAȒx̏ꍇɂ usleep(3) Ɏw肵xԂ
  Ԓx邱ƂɂȂ܂B܂Aw肷p[^̍ŏl 20 ~b
  ł̂AꂪRłB

  ZfBC(\}CNb 20 ~b)KvȏꍇɈԊȒP
  @́A/usr/include/asm/delay.h (linux/include/asm-i386/delay.h)ɒ`
  Ă udelay() gƂ@łB

  udelay() ɓnp[^́A}CNbfBC邩AƂl (unsigned
  long)łBp[^͂ЂƂŁAԂl͂܂B
  ǂꂭ炢fBCׂvZ邽߂̃I[o[wbh邽߁A
  w肵l}CNb]vɃfBCĂ܂\܂B
  (ڍׂ delay.h QƂ̂ƁB)

  J[lȊO udelay() gɂ́Aunsigned long ̕ϐ loops_per_sec 
  K؂Ȓlɐݒ肵ĂKv܂B

  ̒lJ[lĂ@́A(̒mł)A/proc/cpuinfo
  ǂ݂āABogoMips ̒lmA 500000 悶āA
  loops_per_sec ̒lɂƂ@łB(smłǁB)
  (: Linux 2.0.20 ̎̊ cat /proc/cpuinfo ƁA
          processor       : 0
          cpu             : 586
          model           : 7
          vendor_id       : GenuineIntel
          stepping        : unknown
          fdiv_bug        : no
          hlt_bug         : no
          fpu             : yes
          fpu_exception   : yes
          cpuid           : yes
          wp              : yes
          flags           : fpu vme de pse tsc msr mce cx8
          bogomips        : 40.03
  ƂȂ܂B)

  Linux J[l 2.0.x V[Yɂ́Ananosleep(2) ƂVVXeR[
  ǉ܂BgƁA̎ԂɉāAX[v/fBC
  gĂ܂B݂̎ł́A2~bȉ̃fBC̏ꍇɂ udelay()
  Aȏ̏ꍇɂ̓X[vƂӂɂȂĂ悤łB
  łAx͑ς炸}CNbƎv܂AɐVJ[l
  ł͉P邾낤Ǝv܂B

   nanosleep(2) ̃hLg邱Ƃł܂łA
  /usr/src/linux/kernel/sched.c Ȁ(Ăяo):
     int nanosleep(struct timespec *rqtp, struct timespec *rmtp);
  ̂悤łB

  ŁA\ rqtp ɂāAǂꂾ҂w肵܂B
  ܂A rmtp  NULL ȊO̒lŁAnanaosleep() A{[gꂽꍇ
  ɂ(errno ϐ EINTR ɐݒ肳AԂl -1 ƂȂ)Ac莞Ԃ
  \ rmtp ̒Ɋi[܂B
  fBCɊꍇɂ 0 ԂAȂ炩̗RŊȂ
  ꍇɂ -1 Ԃ܂B(̏ꍇɂ errno K؂Ȓlɐݒ肳܂B)

  ɒZfBCKvȏꍇɂ́A@܂B

  |[g 0x80 ɏo(l͂ȂłłB)ƁAvZbT̎ނ
  xɊ֌WȂAقڐm 1}CNb҂Ƃł܂B(o͂̕@
  ɂẮAO̕ǂŉB)Kvȉ񐔌JԂƂŐ}CNb
  ҂Ƃł܂BWIȃ}Vł́Ã|[go͂ɂĂȂɂς
  p肵Ȃ͂(J[lhCołgĂ̂
  ܂)łB
  ̕@ {in|out}[bw]_p() łfBC邽߂ɒʏɎgĂ@
  łB(asm/io.h ĉB)

  ̃vO}ṼvZbT̎ނƃNbNx킩Ă
  ꍇɂ́ÃAZu߂n[hR[h邱ƂŁAƒZfBC
  邱Ƃł܂B(AvZXXPW[OOA
  fBCȂĂ܂Ƃ蓾邱ƂYȂŉB)

  ȉ̕\ł́Aꂼ̖߂ŉNbN(NbN)邩
  ܂BɂĂǂꂭ炢̎Ԃ邩m邱Ƃł܂B
  Ⴆ 50MHz ̃vZbT (486DX-50 ƂA486DX2-50) ̏ꍇɂ 1 NbN
  1/50000000 błB

  Instruction   i386 clock cycles   i486 clock cycles
  nop                   3                   1
  xchg %ax,%ax          3                   3
  or %ax,%ax            2                   1
  mov %ax,%ax           2                   1
  add %ax,0             2                   1
  [oW: Borland Turbo Assembler 3.0 Quick Reference]
  (\Ȃ̂łAyeBAvZbTɂĂ͎͂킩܂B
   炭Ai486 ɋ߂Ǝv܂B)
  (i386  1 NbN̖߂݂͂܂łB)

  ̕\ŁAnop  xchg ͉p͂Ȃ͂łB̖̑߂̓tO
  WX^ύX\܂BłAgcc ͂oĂ܂
  Aɂ͂ȂȂ͂łB

  gɂ́AvO̒ asm(""); ƂgāA
  ̕\̖߂𖄂ߍ݂܂BЂƂ asm() ŕ̖߂𖄂ߍ
  ɂ́Aasm("; ; "); Ƃg܂B

  asm() ́Agcc ɂāACCAZuR[hɕϊ̂
  ֐ĂяõI[o[wbh͂܂B

  ܂AyeBAvZbTł́Au[g猻݂܂ł̌o߃NbN
  TCNm邱Ƃł܂Bȉ̃R[hł:

     extern __inline__ unsigned long long int rdtsc()
     {
       unsigned long long int x;
       __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
       return x;
     }

  ɂÃ݂Ce x86 A[LeN`ł́A1 NbNTCN
  ZfBC͕s\łB

          x̃^C~O: Ԃ̑

  1 b炢̐x̎ԂȂ΁Atime(2) ĝԊȒPł傤B
  ƐmȎԂKvȏꍇɂ́Agettimeofday(2) g ́A}CNb
  ̐x܂B(łAO̕ŏqׂAXPW[ÔƂ͖YȂ
  łB)yeBAvZbT̏ꍇɂ́ÃR[hg 1 NbN
  TCN̐xo܂B

  vZXA鎞Ԍo߂ɃVOi󂯎肽ꍇɂ́Asetitimer(2)
  g܂B̊֐̏ڍׂɂĂ man y[W䗗B

          ̑̃vO~Oɂ

  ȏ̐ł C ɓďqׂ܂AC++  Objective C ł
  悤ɂł͂łB
  AZȕꍇAC ̏ꍇƓl ioperm() iopl() ĂяoȂ
  Ȃ܂񂪁Ǎɂ͒ I/O |[gɑ΂郊[h/Cg(:
  in, out )gƂł܂B

  ̑̌ŁACCAZu C ̃R[h𖄂ߍނƂ
  łȂꍇɂƂȒPȕ@́AKv I/O |[gANZX̂߂
  \[XR[h C ŋLqăRpCAvȎ̕ƃN
  ܂Ƃ@ł傤B

          悭g|[g

  ȉ́Aėp TTL _ I/O |[gɂẴvO~OłB

  p|[g(x[XAhX = /dev/lp0  0x3bcA/dev/lp1  0x378A
  /dev/lp2  0x278): [oW: IBM PS/2 model 50/60 Technical Reference ƁA
  ʂ] (́ArIV|[gŃT|[gĂ ECP/EPP [h
  ǂӂɓ삷̂͒m܂񂪁Aȉŏqׂ(ʂ)|[g
  T|[gĂ͂łB)
  (ʏ̃v^|[gƂē삳łAPrinting-HOWTO 
  ǂނ̂ł傤B)

  قƂǂ̃p|[gɂ́AWIȏo͐p[hɉāAugv
  o[h܂B̃[hł́Arbgݒ肷邱Ƃɂ
  |[go͂܂͓͂ɐؑւ邱Ƃł܂B
  łA͂ǂg[hIɂł̂m܂B
  (ftH[gł̓It̂͂łB)...mĂ烁CB

  BASE + 0 (f[^|[g) ́A|[g̃f[^M𐧌䂵܂B(D0 ` D7 
  rbg0 ` 7 ɑΉ܂B : 0 = low (0V)A1 = high (5V))B
  ̃|[gɑ΂郉Cg̓f[^b`ĊÕsɏo͂܂B
  W܂͊gCg[h̏ꍇɂ́A[hƁAŌɃCgꂽ
  f[^ǂݏo܂Bg[h[h̏ꍇɂ́AOs̃f[^ǂݏo
  ܂B

  BASE + 1 ̃|[g(Xe[^X|[g) ̓[hI[ŁAȉ̂悤
  ͐M̃Xe[^XԂ܂:

  Bit 0  1 ͗\񂳂Ă
  Bit 2   IRQ Xe[^X (Os̒lł͂ȂBǂӂɓ삷邩mȂ)
  Bit 3   ERROR (1=high)
  Bit 4   SLCT  (1=high)
  Bit 5   PE    (1=high)
  Bit 6   ACK   (1=high)
  Bit 7   -BUSY (0=high)
  (high/low ̊tɊւĂ͂܂mł͂܂B)

  BASE + 2 ̃|[g(|[g)̓CgI[([hꍇAŌɃCg
  f[^ԂB)ŁAȉ̃Xe[^XM𐧌䂵܂:

  Bit 0   -STROBE    (0=high)
  Bit 1   AUTO_FD_XT (1=high)
  Bit 2   -INIT      (0=high)
  Bit 3   SLCT_IN    (1=high)
  Bit 4   '1' ɂƁAp|[g̊荞݂(ACK  low -> high 
          JڂŊ荞ݔB)
  Bit 5   g[hł̕(0 = o, 1 = ) 𐧌䂷B̃rbg
          SɃCgI[ŁA[hɂ͕s̒lԂB
  Bit 6  7 ͗\񂳂ĂB
  (JԂ܂Ahigh/low ̊tɊւĂ͂܂mł͂܂B)

  sڑ (25 s D-sub XRlN^) (i=input, o=output):
     1 io   -STROBE
     2 io   D0
     3 io   D1
     4 io   D2
     5 io   D3
     6 io   D4
     7 io   D5
     8 io   D6
     9 io   D7
    10 i    ACK
    11 i    -BUSY
    12 i    PE
    13 i    SLCT
    14 o    AUTO_FD_XT
    15 i    ERROR
    16 o    -INIT
    17 o    SLCT_IN
    18-25   Oh

  IBM ̋Kiɂ΁A1, 14, 16, 17 ԃs(o)́A4.7kI[ 5V 
  vAbvꂽI[vRN^hCo (VN(z) 20mA, \[X
  (fo) 0.55mA, AnCx̏o͂ vAbv 5V)

  ̑̃sɂẮAVN(z) 24mA, \[X(fo) 15mA,
  nCxo͍͂Œł 2.4V, [x̏o͍͂őł 0.5VB

  IBM ȊÕp|[gł͂炭̕WƂ͏XႤꍇł傤B

  Ōɒ: Oh(ڒn)ɂ͋C܂傤B̓Rs[^ғ
  RlN^ڑŁAp|[g󂵂Ă܂o܂B
  lƁA}U[{[hɏĂ̂ł͂Ȃ(gJ[h)p
  |[gĝ܂ˁB
  (: e@̃t[Oh́AƂƂ܂傤ˁB)

  Q[(WCXeBbN)|[g (|[g 0x200-0x207): (ʂ̃WCXeBbN
  𐧌䂷ɂ́AJ[lx̃WCXeBbNhCo܂B
  ftp://sunsite.unc.edu/pub/Linux/kernel/patches/joystick-* 䗗B)

  sڑ (15 s D-sub XRlN^):
  1, 8,  9, 15: +5 V (d)
  4, 5, 12    : Oh
  2, 7, 10, 14: fW^ (Ԃ) BA1, BA2, BB1, BB2
  3, 6, 11, 13: AiO (Ԃ) AX,  AY,  BX,  BY

  +5 V s̓}U[{[h̓dɒڐڑĂ悤ł̂ŁA
  (}U[{[h̍Adɂˑ܂)ɑ̓d͂
  邱Ƃł͂łB

  ̃|[gɂ͓̃WCXeBbNڑł܂A
  fW^͂́Ã{^̓͂łB(WCXeBbN A 
  WCXeBbN B ꂼɓ{^܂B)
  ͒ʏ TTL x̓͂ŁAȉŏqׂXe[^X|[g
  ݂̏ԂǂݏoƂł܂B

  WCXeBbÑ{^Ă low (0V) AłȂ
  high (1K I[̒Rʂ 5V dɃvAbv) ǂݏo܂B

  AiO͂Ƃ̂́Aۂɂ͒RlvĂ̂łB
  ȉł̎dg݂qׂ܂B

  Q[|[gɂ4{̓͂ꂼɃVbg}`oCu[^
  ڑĂ܂B(S(4{) 558 `bv)
  ꂼ̓͂ɂāA̓sƃ}`oCu[^̏o͂̊Ԃ
  2.2K I[̒RA}`oCu[^̏o͂ƃOh̊Ԃ 0.01uF
  ̃^C~OpRfTڑĂ܂Bۂ̃WCXeBbNɂ́A
  X  Y̗̎ɂꂼ|eV[^A+5V Ƃꂼ
  ̓sɐڑĂ܂B(AX, AY WCXeBbN A ɁA
  BX, BY WCXeBbN B ɑΉ܂B)

  (: H}͂Ȋ:

  +5V
   |       ^
   |      /          2.2KI[
   +---/\/\/\--IN----/\/\/\------+
         /                       |
   |eV[^              |
                    +---------+  |
                    | Multi   |  |
                    | vib.   Q|--+
                    |         |  |
                    |         |  |
                    |         |  |
                    |         | === 0.01uF
                    |         |  |
                    +---------+  |
                                 |
                                GND
  )

  }`oCu[^쓮ƁȀo͂ high (5V) ɃhCuA
  ꂼɐڑĂ^C~ORfT̓dʂ 3.3V ɂȂ܂
  ҂Ǎɏo͂ low ɂ܂B̌ʁA}`oCu[^̏o͂
  high ̎Ԃ̓WCXeBbÑ|eV[^̒RlɔႵ܂B
  (܂Aꂼ̎̃WCXeBbN̈ʒu\܂B)
  Rl͈ȉ̎̂Ƃł:
     R = (t - 24.2) / 0.011,
  ŁAR  |eV[^̒Rl(I[)At  high ̎(b)
  łB

  Ƃ܂A킯ł̂ŁAAiO͂ǂݏo߂ɂ́Aȉ
  qׂ悤ɂ܂|[gɃCgāA}`oCu[^쓮Kv
  ܂B

  ̌4̎̏Ԃ|[O(|[gJԂǂݏo)A
  ꂼ̃|[g high  low ɂȂ܂ł̎Ԃ𑪒肵܂B

  ̃|[Oɂ͔ CPU ^C܂ALinux ̂悤
  񃊃A^CE}`^XNVXeł͂̌ʂ͂܂萳mł͂܂B
  |[g₦ԂȂǂݏoƂ͂łȂłB(J[lx̃hCo
  gA|[O̊Ԋ荞݂֎~΂̂łA͍Xɑ
  CPU ^CH܂B)

  āAANZXKv̂|[g͂A0x201 (̃|[gAhX͂
  |[gƓ悤ɂӂ܂AȂɂȂÂǂ炩)łB
  ̃|[gɑ΂郉Cg(ރf[^͂ȂłǂłB)ɂ
  }`oCu[^쓮܂B[hƓ͐M̏ԂԂ܂:

  Bit 0: AX (}`oCu[^o͂̏ (1=high))
  Bit 1: AY (}`oCu[^o͂̏ (1=high))
  Bit 2: BX (}`oCu[^o͂̏ (1=high))
  Bit 3: BY (}`oCu[^o͂̏ (1=high))
  Bit 4: BA1 (fW^ , 1=high)
  Bit 5: BA2 (fW^ , 1=high)
  Bit 6: BB1 (fW^ , 1=high)
  Bit 7: BB2 (fW^ , 1=high)

  ܂ƂȃAiO I/O Kvȏꍇɂ́AADC (AiO -> fW^ Ro[^)
   DAC (fW^ -> AiO Ro[^)`bvp|[gɐڑƂ
  @܂B(qg: dɂ͋CĉBQ[|[g̓d
  gAfBXNhCup̗]ĂdRlN^Rs[^P[X
  oȂǂł傤Bp|[gdƂȂ΁Ad
  ̃foCXgKv܂B)(: ɂA̓fW^n̓d
  łAAiOnɎgꍇɂ͂Ȃ炩̕@ŃfJbvOYȂB)
  ܂́AAD/DA J[hw(قƂǂ I/O |[gŐł܂B)Ƃ
  ܂B

  A1`2`lŏ\łA܂萳młȂĂ悭A(炭)
  smȒ_␳(zeroing)ł悯΁ALinux ̃TEhhCo
  ŃT|[gĂTEhJ[h𔃂ĂĎgAƂ@܂B
  (ɁA\łˁB)

          vO̗

  ́AI/O |[gANZX̒PȃR[fBOł:
  (: Ql܂łɃRg̕oĂ܂Agcc œ{Rg
  g邩ǂA҂͊mFĂ܂B)

  /*
   * example.c: ƂĂȒP |[g I/O ̗
   *
   * ȂɂɂƂ͂Ă܂B|[gɏ݁Aꎞ~āA
   * |[gǂ݂łBugcc -O2 -o example example.cv
   * ƂR}hCŃRpCĉB
   */

  #include <stdio.h>
  #include <unistd.h>
  #include <asm/io.h>

  #define BASEPORT 0x378 /* lp1 */

  int main()
  {
    /* |[gւ̃ANZX𓾂 */
    if (ioperm(BASEPORT,3,1)) {perror("ioperm");exit(1);}

    /* |[g̃f[^ (D0-D7) I[ low (0) ɂ */
    outb(0,BASEPORT);

    /* ΂炭 (100000us = 100ms) X[v */
    usleep(100000);

    /* Xe[^X|[g (BASE + 1) ǂݏoāA\ */
    printf("status: %d\n",inb(BASEPORT+1));

    /* |[ggȂ̂Ōn */
    if (ioperm(BASEPORT,3,0)) {perror("ioperm");exit(1);}

    exit(0);
  }

  /* end of example.c */

          ӎ

  ƂĂ̕珕 (contribute) 󂯂܂̂ŁAɂ͋L
  ܂BFAƂĂ肪ƂB
  ׂĂ̕ɃvC邱Ƃ͂ł܂łXɂ
  ߂ȂAĂxAĂĂ肪ƂB

  End of the Linux I/O port programming mini-HOWTO.

