File: IO-Programming.pl.txt

package info (click to toggle)
doc-linux-pl 2002.06.14-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k, jessie, jessie-kfreebsd, lenny, squeeze, wheezy
  • size: 6,900 kB
  • ctags: 968
  • sloc: makefile: 66
file content (792 lines) | stat: -rw-r--r-- 32,172 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
  Linux I/O port programming mini-HOWTO
  Autor: Riku Saikkonen Riku.Saikkonen@hut.fi
  v, 28 Grudnia 1997
  Wersja polska: Micha Szwaczko michalsz@lena.zsg.lublin.pl
  v1.0, 1 Marca 2000


  Ten dokument HOWTO opisuje programowanie sprztowych rejestrw
  wejcia/wyjcia oraz zatrzymywanie na niewielkie okresy czasu pracy
  programw uytkownika dziaajcych na Linuxie pracujcym w architek
  turze Intel x86.  Dokument zosta napisany w standardzie ISO-8859-2.
  Orygina tego dokumentu znajduje si pod adresem
  ftp://ftp.icm.edu.pl/pub/Linux/sunsite/docs/HOWTO/mini
  ______________________________________________________________________

  Spis treci


  1. Wstp

  2. Uywanie rejestrw wejcia/wyjcia w programach napisanych w C

     2.1 Metoda zwyka
     2.2 Metoda alternatywna: /dev/port

  3. Przerwania (IRQ) oraz dostp DMA

  4. Mierzenie czasu z du dokadnoci

     4.1 Opnienia
        4.1.1 Opnianie za pomoc funkcji sleep() i usleep()
        4.1.2 Opnianie za pomoc funkcji nanosleep()
        4.1.3 Opnianie za pomoc operacji I/O na porcie
        4.1.4 Opnianie za pomoc instrukcji asemblerowych
        4.1.5 Instrukcja rdtsc w Pentium
     4.2 Mierzenie czasu

  5. Inne jzyki programowania

  6. Niektre przydatne porty

     6.1 Port rwnolegy
     6.2 Port joysticka/Port gier
     6.3 Port szeregowy

  7. Porady

  8. W razie kopotw

  9. Przykadowy program

  10. Wyrazy uznania

  11. Od tumacza



  ______________________________________________________________________

  11..  WWssttpp

  Ten dokument HOWTO opisuje programowanie sprztowych rejestrw
  wejcia/wyjcia oraz zatrzymywanie na niewielkie okresy czasu pracy
  programw uytkownika dziaajcych na Linuxie pracujcym w
  architekturze Intel x86. Dokument ten jest nastpc bardzo maego IO-
  port mini-HOWTO tego samego autora.  Dokument zosta napisany przez
  Riku Saikkonen. Copyright 1995-1997 Riku Saikkonen. Po szczegy
  odnonie praw autorskich zobacz Linux HOWTO copyright
  <http://sunsite.icm.edu.pl/pub/Linux/sunsite/docs/HOWTO/COPYRIGHT>.
  Jeli chcesz co poprawi lub doda to miao moesz do mnie pisa
  (Riku.Saikkonen@hut.fi)...

  Zmiany w stosunku do poprzedniej wersji (30 Marca 1997):

    Wyjanienie kwestii odnoszcych si do inb_p/outb_p oraz portu 0x80

    Usunicie informacji o udelay(), jako e nanosleep() zapewnia
     janiejszy sposb jego uycia.

    Przeksztacenie dokumentu na format SGML-Linuxdoc oraz niewielka
     reorganizacja.

    Wiele mniejszych dodatkw i modyfikacji.


  22..  UUyywwaanniiee rreejjeessttrrww wweejjcciiaa//wwyyjjcciiaa ww pprrooggrraammaacchh nnaappiissaannyycchh ww CC

  22..11..  MMeettooddaa zzwwyykkaa

  Procedury dostpu do portw (rejestrw) we/wy umieszczone s w
  /usr/include/asm/io.h (lub w linux/include/asm-i386/io.h w rdach
  jdra) Procedury te wystpuj w formie makr do wstawienia a wic
  wystarczy e zrobisz #include <asm/io.h>; nie potrzebujesz ju adnych
  dodatkowych bibliotek.

  Z powodu ogranicze w gcc (obecna wersja 2.7.2.3 i poniej) oraz egcs
  (wszystkie wersje) programy wykorzystujce te procedury _m_u_s_z_ by
  kompilowane z wczon optymalizacj (gcc -O1 lub wicej) lub moesz
  te zrobi #define extern bez parametru (puste) zanim wczysz
  <asm/io.h>.

  Do odpluskwiania (debugging) moesz uy gcc -g -O (przynajmniej w
  nowoczesnych wersjach gcc), chocia optymalizacja moe spowodowa, i
  debugger bdzie zachowywa si troch dziwnie. Jeli to sprawia Ci
  kopot, procedury korzystajce z rejestrw we/wy wstaw do osobnego
  pliku i tylko ten plik poddaj optymalizacji podczas kompilacji.

  Zanim dostaniesz si do jakiegokolwiek portu we/wy, musisz nada swemu
  programowi uprawnienia do tego. Robi si to wywoujc funkcj ioperm()
  (zdeklarowan w unistd.h i zdefiniowan w jdrze) gdzie w okolicach
  pocztku programu (przed jakimkolwiek dostpem do portw) Skadnia
  tego polecenia to ioperm(skd,ile,wacz) gdzie skd jest pierwszym
  portem do ktrego chcesz mie dostp a ile liczb kolejnych portw do
  ktrych chcesz mie dostp.  Dla przykadu ioperm(0x300, 5, 1) da ci
  dostp do portw od 0x300 do 0x304 (w sumie pic portw). Ostatni
  argument to wartoc logiczna mwica o tym czy program otrzyma dostp
  do portw (1 - prawda) bd nie (0 - fasz).  Moesz wywoywa
  ioperm() wiele razy aby wczy wiele niecigych obszarw rejestrw.
  Zajrzyj do ioperm(2) w podrczniku systemowym man po szczegy
  odnonie skadni.

  Wywoanie ioperm() wymaga aby twj program mia uprawnienia root'a:
  wobec czego albo musisz uruchamia go jako root albo da mu suid
  root'a.  Po wywoaniu ioperm() moesz ju zrezygnowa z uprawnie
  root'a.  Nie wymaga si aby w sposb jawny wycza uprzywilejowany
  dostp do portw (czyli ioperm(....,0)) na kocu programu; robi si to
  automatycznie wraz z zakoczeniem procesu.

  Funkcja setuid() w wypadku uytkownika bez przywilejw root'a nie
  odbiera dostpu do portw przydzielonego przez ioperm() ale funkcja
  fork() ju tak. (proces potomny nie dostaje dostpu ale proces-rodzic
  go zachowuje)
  ioperm() moe jedynie umoliwi dostp do portw od 0x000 do 0x3FF.
  Jeli chcesz uywa innych portw (wyszych) musisz uy funkcji
  iopl() (ktra daje ci dostp do wszystkich portw od razu) Uyj
  argumentu 3 (czyli iopl(3)) aby da swemu programowi dostp do
  _w_s_z_y_s_t_k_i_c_h portw (bd ostrony - dostp do niewaciwych portw moe
  wywoa najrniejsze usterki komputera).  Musisz mie uprawnienia
  root'a aby wywoa iopl(). Po szczegly zajrzyj do podrcznika
  systemowego man: iopl(2)

  Teraz waciwy dostp do portw.. Aby odczyta bajt (8 bitw) z portu,
  wywoaj funkcj inb(port), zwraca ona odczytan warto.  Aby zapisa
  bajt do portu wywoaj outb(warto,port) (zwr uwag na kolejno
  argumentw) Aby odczyta sowo (16 bitw) z portw x i x+1 (jeden bajt
  z kadego czone w sowo za pomoc asemblerowej instrukcji inw)
  wywoaj inw(x) Aby zapisa sowo do tych dwch portw uyj
  outw(warto,x) Jeli nie jeste pewien ktrej instrukcji uy
  (operujcej bajtem czy sowem) prawdopodobnie bdziesz chcia uy
  inb() i outb() - wikszo urzdze zaprojektowana jest z bajtowo-
  zorientowanym dostpem do portw.  Zauwa, e wykonanie kadej
  instrukcji operujcej na portach zajmuje co najmniej mikrosekund.

  Makra inb_p(),outb_p(),inw_p() i outw_p() dziaaj identycznie z tymi
  powyej ale dodatkowo wykonuj opnienie (okoo 1 mikrosekundy) po
  dostpie do portu. Moesz spowodowa e opnienie bdzie wartoci ok
  4 mikrosekund jeli zrobisz #define REALLY_SLOW_IO zanim wczysz
  <asm/io.h> Makra te zwykle (chyba e zrobisz #define
  SLOW_IO_BY_JUMPING, ktre jest raczej mniej dokadne) uywaj zapisu
  do portu 0x80 zby uzyska opnienie, wobec czego musisz najpierw da
  dostp do portu 0x80 za pomoc ioperm(). Zapisy do portu 0x80 nie
  powinny mie wpywu na adn czs systemu. Jeli chcesz pozna
  bardziej wszechstronne metody dostpu do portw czytaj dalej.

  W stosunkowo nowych dystrybucjach podrcznika systemowego man znajduj
  si strony ioperm(2), iopl(2) oraz powyszych makr.


  22..22..  MMeettooddaa aalltteerrnnaattyywwnnaa:: //ddeevv//ppoorrtt

  Innym sposobem dostpu do rejestrw I/O jest otworzenie urzdzenia
  /dev/port do zapisu lub/i odczytu za pomoc funkcji open() (/dev/port
  to urzdzenie znakowe, numer gwny 1, poboczny 4) (Funkcje f*() z
  biblioteki stdio maj wewntrzne buforowanie wic ich unikaj)
  Nastpnie wywoaj lseek() do odpowiedniego bajtu w tym pliku (pozycja
  0 = port 0x00 pozycja 1 = port 0x01 itd) i czytaj (read()) lub zapisuj
  (write()) bajt lub sowo.

  Oczywicie aby to zadziaao twj program musi mie moliwoc czytania
  i zapisywania do /dev/port.  Metoda ta jest prawdopodobnie wolniejsza
  od metody normalnej pokazanej powyej ale nie potrzebuje ani
  optymalizacji programu ani wywoywania ioperm().  Nie potrzebuje te
  uprawnie root'a jeli nadasz zwykym uytkownikom lub jakiej grupie
  prawa dostpu do /dev/port - jest to jednak nieporzdane z punktu
  widzenia bezpieczestwa systemu, jako e moliwe jest wtedy
  uszkodzenie systemu, a moe nawet zdobycie przywilejw root'a przez
  bezporedni dostp za pomoc /dev/port do dyskw, kart sieciowych itp.


  33..  PPrrzzeerrwwaanniiaa ((IIRRQQ)) oorraazz ddoossttpp DDMMAA

  Nie mona bezporednio korzysta z IRQ lub DMA w programach
  uytkownika.  Musisz napisa sterownik/modu do jdra; zajrzyj do The
  Linux Kernel Hacker's Guide po szczegy a take do rde jdra po
  przykady.  W programach uytkownika nie mona te przerwa wycza.



  44..  MMiieerrzzeenniiee cczzaassuu zz dduu ddookkaaddnnooccii

  44..11..  OOppnniieenniiaa

  Przede wszystkim trzeba stwierdzi e z powodu wielozadaniowej natury
  Linuxa nie mona zagwarantowa e procesy w trybie uytkownika bd
  mie dokadn kontrol czasu. Twj proces moe zosta rozpoczty w
  kadej chwili i moe mu to zaj od 10 milisekund do kilku sekund (na
  bardzo obcionych systemach). Jednake, dla wikszoci aplikacji
  uywajcych portw I/O nie ma to wikszego znaczenia.  Aby
  zminimalizowa to zjawisko moesz nada swemu procesowi wyszy
  priorytet (zobacz nice(2) w podrczniku man) lub uywa zarzdzania
  procesami w czasie rzeczywistym (patrz niej)

  Jeli chcesz berdziej precyzyjnie odmierza czas ni pozwalaj ci na
  to procesy w trybie uytkownika, moesz skorzysta ze wsparcia dla
  procesw uytkownika w czasie rzeczywistym. Jdra 2.x.x maj
  niewielkie wsparcie dla czasu rzeczywistego; zobacz
  sched_setscheduler(2) w podrczniku man. Jest rwnie specjalne jdro
  ktre ma zaawansowane wsparcie dla czasu rzeczywistego. Zobacz
  <http://luz.cs.nmt.edu/~rtlinux> aby uzyska wicej informacji na ten
  temat.


  44..11..11..  OOppnniiaanniiee zzaa ppoommoocc ffuunnkkccjjii sslleeeepp(()) ii uusslleeeepp(())

  Zacznijmy teraz od atwiejszych wywoa. Jeli chcesz opnie rzdu
  sekund to najpewniej jest uy sleep(). Dla opnie rzdu
  przynajmniej dziesitek milisekund (10ms wydaje si by najmniejszym
  moliwym opnieniem) powiniene uy usleep().  Funkcje te oddaj
  czas innym procesom a wic czas procesora nie jest marnowany. Zajrzyj
  do sleep(3) i usleep(3) w podrczniku man po szczegy dotyczce tych
  funkcji.

  Jeli potrzebujesz opnie mniejszych ni 50 milisekund (w zalenoci
  od prdkoci procesora i samego komputera oraz obcienia systemu)
  oddawanie czasu procesora zajmuje zbyt wiele czasu poniewa linuxowy
  zarzdca procesw (w architekturze x86) zwykle zabiera okoo 10-30
  milisekund zanim zwrci kontrol do twojego procesu.  Z tego powodu
  dla maych opnie usleep() zwykle opnia o troch wicej czasu ni
  podajesz w parametrze a przynajmniej okoo 10 ms.


  44..11..22..  OOppnniiaanniiee zzaa ppoommoocc ffuunnkkccjjii nnaannoosslleeeepp(())

  W serii jder 2.0.x znajduje si nowa funkcja systemowa nanosleep()
  (zobacz nanosleep(2) w podrczniku man) ktra pozwala opnia lub
  zatrzymywa proces na krtkie okresy czasu (kilka mikrosekund lub
  wicej).

  Dla uzyskania opnie <=2ms, jeli (i tylko wtedy) twj proces jest
  ustawiony na zarzdzanie z wsparciem dla czasu rzeczywistego (poprzez
  sched_setscheduler()), nanosleep() uywa ptli opniajcej; w
  przeciwnym razie zatrzymuje proces tak jak usleep().

  Ptla opniajca uywa udelay() (wewntrznej funkcji jdra utwanej
  przez wiele jego moduw) a dugo ptli jest obliczana na podstawie
  wartoci BogoMips (prdko tego rodzaju ptli opniajcej jest jedn
  z rzeczy ktr BogoMips dokadnie mierzy) Zobacz
  /usr/include/asm/delay.h po szczegy odnonie dziaania tego
  mechanizmu.





  44..11..33..  OOppnniiaanniiee zzaa ppoommoocc ooppeerraaccjjii II//OO nnaa ppoorrcciiee

  Inn metod opniania o niewielkie iloci mikrosekund s operacje I/O
  na portach.  Czytanie/zapisywanie jakiegokolwiek bajtu z/do portu 0x80
  (patrz wyej jak to si robi) powinno da opnienie prawie dokadnie
  1 mikrosekundy bez wzgldu na typ procesora i jego prdko. Moesz
  tak robi wiele razy aby uzyska opnienie rzdu kilku mikrosekund.
  Sposb ten nie powinien wywoywa adnych szkodliwych efektw
  ubocznych na adnym standardowym komputerze (nawet niektre moduy
  jdra go uywaj). W ten sposb uzyskuj opnienie funkcje
  {in|out}[bw]_p() (zobacz asm/io.h).

  W zasadzie, instrukcje I/O na wikszoci portw w obszarze 0-0x3ff
  zbieraj prawie dokadnie 1 mikrosekund, wic jeli na przykad
  uywasz bezporednio portu rwnolegego po prostu wykonaj kilka razy
  inb() z tego portu aby uzyska opnienie.


  44..11..44..  OOppnniiaanniiee zzaa ppoommoocc iinnssttrruukkccjjii aasseemmbblleerroowwyycchh

  Jeli znasz typ procesora i prdkoc zegara w komputerze na ktrym
  bdzie dziaa twj program, moesz na stae uzyska krtsze
  opnienia poprzez zastosowanie pewnych rozkazw asemblerowych
  (pamitaj jednak e twj proces moe si zacz w dowolnym momencie
  wobec czego opnienia te mog by wiksze od czasu do czasu) W tabeli
  poniej wewntrzna prdko procesora okrela liczb cykli np dla
  procesora 50MHz (np. 486DX-50 lub 486DX2-50) jeden cykl zegara zajmuje
  1/50000000 sekundy. (200 nanosekund).


       Instrukcja   cykle zegara na 386    cykle zegara na 486
       nop                   3                   1
       xchg %ax,%ax          3                   3
       or %ax,%ax            2                   1
       mov %ax,%ax           2                   1
       add %ax,0             2                   1




  (Przykro mi ale niewiele wiem o Pentium. Pewnie podobnie do 486. Nie
  mog znale adnej instrukcji ktra zajmowaa by tylko jeden cykl
  zegara na 386. Jeli moesz, uywaj instrukcji jednocyklowych, w prze
  ciwnym razie architektura potokowa (pipelining) uywana w nowoczesnych
  procesorach moe da jeszcze krtsze czasy)

  Rozkazy nop i xchg z tabeli powyej nie powinny powodowa adnych
  skutkw ubocznych. Reszta moe modyfikowa rejestr znacznikw ale nie
  powinno mie to znaczenia bo gcc powinno to wykry. Uycie nop jest
  dobrym wyborem.

  Aby skorzysta z powyszego, trzeba w swoim programie wywoa funkcj
  asm("instrukcja") Skadnia instrukcji jest taka sama jak w tabeli
  powyej. Jeli chcesz uy kilku instrukcji w jednym wywoaniu funkcji
  asm rozdziel je rednikami.  Na przykad asm("nop ; nop ; nop ; nop")
  wywoa cztery razy instrukcj nop opniajc nasz program o 4 cykle na
  486 lub Pentium (lub 12 cykli na 386)

  Funkcja asm() jest przez gcc tumaczona na wstawk w asemblerze a wic
  nie ma zagroenia przekroczenia limitu wywoa funkcji.

  Opnienia krtsze ni jeden cykl zegara nie s moliwe w
  architekturze Intel i386.



  44..11..55..  IInnssttrruukkccjjaa rrddttsscc ww PPeennttiiuumm

  Jeli masz Pentium, moesz odczyta ilo cykli zegara ktre upyny
  od ostatniego uruchomienia komputera. Robi si to za pomoc takiego
  kodu w C:


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




  Moesz odczytywa t warto w celu opniania o dowoln ilo cykli.



  44..22..  MMiieerrzzeenniiee cczzaassuu

  Dla czasw rzdu sekundy prawdopodobnie najatwiej bdzie uy funkcji
  time().  Dla bardziej dokadnych pomiarw: gettimeofday() jest
  dokadne co do mikrosekundy (ale zobacz wyej o zarzdzaniu procesami)
  Dla Pentium fragment kodu rdtsc powyej jest dokadny co do cykla
  zegarowego.

  Jeli chcesz aby twj proces dostawa jaki sygna po jakim czasie,
  uyj settimer() lub alarm(). Zajrzyj do stron podrcznika man
  dotyczcych tych funkcji.


  55..  IInnnnee jjzzyykkii pprrooggrraammoowwaanniiaa

  Opis powyej koncentruje si na jzyku C. Powinien bezporednio
  odnoi si te do C++ i Objective C. W asemblerze musisz wywoa
  ioperm() lub iopl() tak jak w C ale potem moesz ju uywa instrukcji
  czytania/zapisywania portw bezporednio.

  W innych jzykach, jeli nie moesz wstawia do programu wstawek w
  asemblerze lub C bd jeli nie moesz uy funkcji systemowych
  opisanych powyej, najatwiej bdzie napisa osobny program w C ze
  wszystkimi operacjami na portach I/O i wszystkimi opnieniami ktrych
  potrzbujesz po czym skompilowa go i zlinkowa z reszt twojego
  programu. Moesz te uy /dev/port jak to opisano powyej.


  66..  NNiieekkttrree pprrzzyyddaattnnee ppoorrttyy

  Teraz troch informacji programistycznych dotyczcych zwykych portw
  ktre mog by bezporednio uyte do operacji I/O w logice TTL (lub
  CMOS).

  Jeli chcesz uywa tych lub innych zwykych portw zgodnie z ich
  normalnym przeznaczeniem (np chcesz sterowa normaln drukark bd
  modemem) powiniene najpewniej uy istniejcych sterownikw (zwykle
  doczonych do jdra) zamiast programowa porty bezporednio jak to
  opisuje ten dokument. Ten rozdzia jest dla tych ktrzy chc podczy
  do standardowych portw komputera wywietlacze LCD, silniki krokowe
  lub inne niestandardowe urzdzenia elektroniczne.


  Jeli chcesz sterowa jakim urdzeniem produkowanym na rynek masowy,
  np. skanerem (ktre to urzdzenie jest ju na rynku jaki czas)
  poszukaj raczej istniejcego sterownika Linuxowego. Dobrym miejscem
  aby zacz jego poszukiwania jest Hardware-HOWTO

  www.hut.fi/Misc/Electronics jest dobrym rdem informacji dotyczcych
  podczania urzdze do komputera (jak i samej elektroniki w ogle)


  66..11..  PPoorrtt rrwwnnoolleeggyy

  Adres bazowy portu rwnolegego (zwany poniej >BASE) to 0x3bc dla
  /dev/lp0, 0x378 dla /dev/lp1 i 0x278 dla /dev/lp2.  Jeli chcesz
  sterowa tylko czym co dziaa jak normalna drukarka powiniene
  zapozna si z Printing-HOWTO.

  Oprcz standardowego trybu tylko-do-zapisu opisanego powyej, w
  wikszoci portw rwnolegych istnieje jeszcze rozszeony tryb
  dwukierunkowy. Po informacje na ten temat oraz na temat nowych trybw
  ECP/EPP (jak i samego standardu IEEE 1284 w ogle) zajrzyj na
  http://www.fapo.com oraz na
  http://www.senet.com.au/~cpeacock/parallel.htm Pamitaj, e skoro nie
  moesz uywa DMA i IRQ w programach uytkownika, aby uy trybw
  ECP/EPP bdziesz prawdopodobnie musia napisa wasny sterownik do
  jdra.  Zdaje si, e kto ju pisze taki sterownik ale nie znam
  szczegw.

  Port BASE+0 (port danych) kontroluje sygnay danych portu (D0 do D7
  dla bitw od 0 do 7) Stany: 0=niski (0 V), 1=wysoki (5 V). Zapis do
  tego portu zatrzaskuje dane na pinach.  Odczyt zwraca ostatnio
  zapisan dan w trybie normalnym bd rozszeonym lub dane z innego
  urzdzenia w rozszeonym trybie odczytu.

  Port BASE+1 (port statusu) jest tylko-do-odczytu i zwraca stan
  poniszych sygnaw wejsciowych.

    Bity 0 i 1 s zarezerwowane.

    Bit 2  Status IRQ (nie jest to sygna z pina - nie wiem w jaki
     sposb to dziaa)

    Bit 3  ERROR (1=stan wysoki)

    Bit 4  SLCT  (1=stan wysoki)

    Bit 5  PE    (1=stan wysoki)

    Bit 6  ACK   (1=stan wysoki)

    Bit 7  -BUSY (0=stan wysoki)

     (Nie jestem pewien stanw tych bitw.)

  Port BASE+2 (Port kontrolny) jest tylko do zapisu (odczyt zwraca
  ostatnio zapisan warto) i kontroluje ponisze sygnay kontrolne:

    Bit 0 -STROBE (0=stan wysoki)

    Bit 1 AUTO_FD_XT (1=stan wysoki)

    Bit 2 -INIT (0=stan wysoki)

    Bit 3 SLCT_IN (1=stan wysoki)

    Bit 4 gdy ustawiony na 1 - wcza IRQ portu rwnolegego (co ma
     miejsce przy przejsciu sygnau ACK ze stanu niskiego do wysokiego)
    Bit 5 kontroluje kierunek danych w trybie rozszeonym (0 = zapis, 1
     = odczyt) i jest cakowicie tylko-do-zapisu. (Odczyt nie zwraca
     niczego uytecznego dla tego bitu).

    Bity 6 i 7 s zarezerwowane.

     (Znowu nie jestem pewien stanw.)

  Rozkad wyprowadze. (25 pinowe eskie gniazdo typu D) (i=wejscie,
  o=wyjscie):


       1io -STROBE, 2io D0, 3io D1, 4io D2, 5io D3, 6io D4, 7io D5, 8io D6,
       9io D7, 10i ACK, 11i -BUSY, 12i PE, 13i SLCT, 14o AUTO_FD_XT,
       15i ERROR, 16o -INIT, 17o SLCT_IN, 18-25 Ground




  Specyfikacja IBM twierdzi e piny 1,14,16 i 17 (wyjscia kontrolne)
  maj otwarte kolektory podpite do +5V przez 4.7 kiloomowe oporniki
  (dostarcza 20 mA, pobr 0.55 mA, wyjscie w stanie wysokim +5V minus to
  co podpite) Reszta pinw pobiera 24 mA, dostarcza 15 mA a wyjscie w
  stanie wysokim to minimum 2.4V. Stan niski dla wszystkich to maximum
  0.5V. Porty rwnolege inne ni IBM prawdopodobnie odbiegaj od tego
  standardu.  Po wicej informacji na ten temat zajrzyj na
  http://www.hut.fi/Misc/Electronics/circuits/lptpower.html

  Na koniec jeszcze ostrzeenie: Uwaaj z uziemieniem. Zepsuem ju par
  portw przez podczanie si do nich gdy komputer by wczony. Dobrze
  jest w takim wypadku uywa portw rwnolegych nie zintegrowanych z
  pyt gwn (zwykle mona doda drugi port rwnolegy do komputera za
  pomoc taniej standardowej karty I/O (tzw ajoki - tum); po prostu
  wycz porty ktrych nie potrzebujesz i ustaw adres portu na karcie IO
  na jaki wolny adres. Nie musisz si martwi o IRQ dla portu
  rwnolegego gdy normalnie si go nie uywa)


  66..22..  PPoorrtt jjooyyssttiicckkaa//PPoorrtt ggiieerr

  Port gier jest umieszczony pod adresami 0x200-0x207. Jeli chcesz
  kontrolowa normalny joystick to jest do tego specjalny sterownik w
  jdrze, zobacz
  <ftp://sunsite.icm.edu.pl/sunsite/pub/Linux/kernel/patches> Plik
  nazywa si joystick-*.

  Rozkd wyprowadze od stony portu (15-pinowe eskie gniazdo typu D-
  shell):

    piny 1,8,9,15: +5 V (zasilanie)

    piny 4,5,12: Masa

    piny 2,7,10,14: Wejscia cyfrowe (Odpowiednio: BA1, BA2, BB1, i BB2)

    piny 3,6,11,13: Wejscia ``analogowe'' (Odpowiednio: AX, AY, BX, i
     BY)

  Piny +5V zwykle s podczane bezporednio do linii zasilania na
  pycie gwnej, wic, w zalenoci od pyty, zasilacza i portu
  ,powinny dawa cakiem sporo mocy.  Cyfrowe wejcia s uywane dla
  przyciskw joystickw ktre moesz sobie podczy do portu (joystick
  A i B, dwa przyciski kady) Wejcia te powinny by na poziomach TTL a
  ich stan moesz odczyta z portu statusu (zobacz poniej) Prawdziwy
  joystick zwraca stan niski (0V) kiedy przycisk jest nacinity a stan
  wysoki (+5V z pinw zasilajcych przez jednokiloomowy rezystor) kiedy
  jest zwolniony.

  Tak-zwane wejcia analogowe w istocie mierz opr. Port joysticka ma
  przyczony do tych 4 wej poczwrny multiwibrator (quad one-shot
  multivibrator) (scalak 558) Na kadym wejciu mamy rezystor 2.2k
  pomidzy pinem  a wejciem multiwibratora oraz kondensator 0.01uF
  pomidzy wyjciem multiwibratora a mas.  Prawdziwy joystick ma
  jeszcze potencjometr dla kadej z osi (X i Y) umieszczony pomidzy +5V
  a waciwym pinem wejsiowym (AX lub AY dla joysticka A oraz BX lub BY
  dla joysticka B)

  Kiedy jest aktywny, multiwibrator ustawia swoje wyjcia w stan wysoki
  (5V) i oczekuje a kady z kondensatorw osignie 3.3V po czym ustawia
  w stan niski odpowiednie linie wyjciowe. Dlatego wanie czas trwania
  okresu kiedy multivibrator jest w stanie wysokim jest proporcjonalny
  do oporu potencjometru joysticka.  (czyli pozycji joysticka na
  odpowiedniej osi) Relacja wyglda tak:

       R = (t - 24.2) / 0.011,


  gdzie R to opr potencjometru w omach a t to czas trwania stanu wysok
  iego w sekundach.

  Wobec tego aby odczyta wejia analogowe musisz najpierw uaktywni
  multiwibrator (za pomoc zapisu do odpowiedniego portu - patrz niej)
  po czym odczytywa stan czterech osi (za pomoc nastpujcych po sobie
  odczytw z portw) a zmieni stan z wysokiego na niski po czym
  mierzysz czas trwania stanu wysokiego.  Odczytywanie takie zuywa
  sporo czasu procesora, co w systemie wielozadaniowym takim jak Linux
  nie bdcym systemem czasu rzeczywistego powoduje niedokdno
  rezultatw gdy nie mona odczytywa portu stale (chyba e uyjesz
  sterownika niskopoziomowego i wyczysz przerwania na czas odczytw -
  ale to zabiera jeszcze wicej czasu procesora).  Jeli wiesz e
  przejcie do stanu niskiego zajmie sygnaowi duzy czas (rzdu 10
  ms) moesz uy usleep() przed odczytem oddajc w ten sposb czas
  procesora innym procesom.

  Jedynym portem do ktrego potrzebujesz mie dostp to port 0x201 (inne
  porty zachowuj si identycznie bd nie robi nic). Kady zapis (nie
  wane czego) do tego portu uaktywnia multiwibrator. Odczyt z tego
  portu zwraca stan poszczeglnych sygnaw wejciowych.


    Bit 0: AX (stan (1=stan wysoki) wyjia  multiwibratora)

    Bit 1: AY (stan (1=stan wysoki) wyjia  multiwibratora)

    Bit 2: BX (stan (1=stan wysoki) wyjia  multiwibratora)

    Bit 3: BY (stan (1=stan wysoki) wyjia  multiwibratora)

    Bit 4: BA1 (wejie cyfrowe, 1=stan wysoki)

    Bit 5: BA2 (wejie cyfrowe, 1=stan wysoki)

    Bit 6: BB1 (wejie cyfrowe, 1=stan wysoki)

    Bit 7: BB2 (wejie cyfrowe, 1=stan wysoki)



  66..33..  PPoorrtt sszzeerreeggoowwyy

  Jeli urzdzenie z ktrym si komunikujesz przypomina co co dzia
  jak RS-232 mosz do tego celu uy portu szeregowego.  Linuxowy
  sterownik portu szeregowego powinien wystarczy w prawie wszystkich
  zastosowaniach (nie powinienne mie potrzeby programowa port
  bezporednio, a nawet jeli chciaby to robi prawdopodobnie
  musiaby napisa wasny modu do jdra.)  Sterownik Linuxowy jest
  cakiem wszechstronny a wic uywanie na przykad niestandardowych
  prdkoci portu nie powinno by problemem.

  Jeli chcesz dowiedzie si wicej o programowaniu portu szeregowego w
  Linuxie zobacz stron termios(3) w podrczniku systemowym man, rda
  sterownika (linux/drivers/char/serial.c), i
  <http://www.easysw.com/~mike/serial/index.html>.



  77..  PPoorraaddyy

  Jeli zaley Ci na dobrej obsudze analogowej transmisji I/O, moesz
  podczy do portu rwnolegego przetworniki analogowo-cyfrowe bd
  cyfrowo-analogowe (ADC,DAC).(Podpowied: we zasilanie z portu
  joysticka bd z wolnej wtyczki zasilania dysku twardego wyprowadzonej
  na zewntrz obudowy, chyba e masz urzdzenie nie wymagajce duej
  mocy, wtedy moesz wzi zasilanie z samego portu. Moesz te uy
  zewntrznego zasilacza.) Moesz te kupi kart przetwornikw
  analogowo-cyfrowych i cyfrowo analogowych (AD/DA) (wikszo
  starszych/wolniejszych takich kart jest sterowana za pomoc portw
  I/O) Jeli nie przeszkadza ci ma ilo kanaw (1 lub 2)
  niedokadno oraz (moliwe) ze zerowanie, dobra (i szybka) bdzie
  tania karta dwikowa wspierana przez Linuxowy sterownik.

  W czuych urzdzeniach analogowych niewaciwe uziemienie mo
  spowodowa bdy na wejciach bd wyjciach. Jeli przytrafi Ci si
  co takiego, moesz sprbowa odizolowa elektrycznie urzdzenie od
  komputera przez uycie transoptorw (optocouplers) na _w_s_z_y_s_t_k_i_c_h
  sygnaach pomidzy Twoim urzdzeniem a komputerem.  Aby zapewni
  lepsz izolacj zasilanie do transoptorw sprbuj wzi z komputera
  (wolne sygnay na porcie mog da wystarczajc ilo mocy)

  Jeli szukasz oprogramowania do projektowania pytek drukowanych na
  Linuxa to jest darmowa aplikacja ktra nazywa si Pcb i powinna
  sprawia si dobrze, przynajmniej wtedy kiedy nie robisz czego bardzo
  skomplikowanego. Zaczona jest ona do wielu dystrybucji Linuxa a
  dostpna na
  <ftp://sunsite.icm.edu.pl/pub/Linux/sunsite/apps/circuits/> (plik
  pcb-*).



  88..  WW rraazziiee kkooppoottww


     PP11..
        Dostaje bd segmentacji pamici kiedy dobieram si do portw


     OO11..
        Albo twj program nie ma uprawnie root'a bd wywoanie
        ioperm() nie powiodo si z jakiego innego powodu.  Sprawd
        warto powrotn funkcji ioperm(). Sprawd rwnie czy
        rzeczywiie operujesz na portach do ktrych uzyskae dostp za
        pomoc ioperm() (zobacz P3).  Jeli uywasz makr opniajcych
        (inb_p(), outb_p(), itd), pamitaj aby wywoa ioperm() rwnie
        wtedy jeli chcesz uzyska dostp do portu 0x80


     PP22..
        Nie mog nigdzie znale deklaracji funkcji in*(), out*() i gcc
        narzeka na niezdefiniowane referencje.


     OO22..
        Nie kompilowae z wczon optymalizacj (-O), i w ten sposb
        gcc nie mg odnale makr w katalogu asm/io.h. Albo nie
        wczye w ogle <asm/io.h> do swojego programu.


     PP33..
        Wywonie out*() nie robi nic bd robi co dziwnego.


     OO33..
        Sprawd kolejno parametrw; powinno by outb(warto, port), a
        nie outportb(port, warto) co jest popularne w MS-DOS.


     PP44..
        Chc sterowa standardowym urzdzeniem RS-232/portem
        rwnolegym/drukark/joystickiem


     OO44..
        Lepiej bdzie jak uyjesz istniejcych sterownikw z jdra, X
        serwera lub czego innego.  Sterowniki te s zazwyczaj dosy
        wszechstronne wic nawet lekko niestandardowe urzdzenia z nimi
        wsppracuj. Zobacz wyej informacje o zwykych portach, s tam
        odnoniki do stosownej dokumentacji.




  99..  PPrrzzyykkaaddoowwyy pprrooggrraamm

  Oto kawaek prostego przykadowego programu demonstrujcego dostp do
  rejestrw I/O.





























  ______________________________________________________________________
  /*
   * example.c: bardzo prosty przykad dostpu do portw I/O
   *
   * Program ten nie robi nic uytecznego, zapisuje do portu, czeka i
   * odczytuje z portu. Kompilacja: gcc -O2 -o example example.c
   * Uruchamiac jako ./example bdc root'em
  /

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

  #define BASEPORT 0x378 /* lp1 */

  int main()
  {
    /* Uzyskaj dostp do portw */
    if (ioperm(BASEPORT, 3, 1)) {perror("ioperm"); exit(1);}

    /* Ustaw wszystkie bity danych (D0-D7) w stan niski (0) */
    outb(0, BASEPORT);

    /* Zaczekaj chwilk (100 ms) */
    usleep(100000);

    /* Odczytaj z rejestru statusowego (BASE+1) i wywietl rezultat */
    printf("status: %d\n", inb(BASEPORT + 1));

    /* Ju nie potrzebujemy portw */
    if (ioperm(BASEPORT, 3, 0)) {perror("ioperm"); exit(1);}

    exit(0);
  }
  /* koniec example.c */
  ______________________________________________________________________




  1100..  WWyyrraazzyy uuzznnaanniiaa

  Pomogo mi zbyt wiele osb aby je tutaj wszystkie wymieni, ale
  wszystkim bardzo dzikuj. Nie odpowiedziaem im wszystkim;
  przepraszam za to i jeszcze raz dziki za pomoc.

  1111..  OOdd ttuummaacczzaa

  Niniejsze tumaczenie objte jest prawami autorskimi Michaa Szwaczko.
  Dozwolone jest rozpowszechnianie i dystrybucja na prawach takich
  samych jak dokument oryginalny.(Zobacz HOWTO-Copyright)

  Zmiany wprowadzone przeze mnie do dokumentu polegaj na zastpieniu
  adresw niektrych serwerw ftp przez ich mirrory w Polsce.

  Zdaj sobie spraw e tumaczenie nie jest wolne od wad i bdw.
  Jeli znajdziesz jakie, prosz napisz do mnie:
  michalsz@lena.zsg.lublin.pl

  Oficjaln stron grupy tumaczy HOWTO jest http://www.jtz.org.pl