FAQ pentru Tema 2

Întrebări generale

1 - Treaba cu COM1 și COM2

Context

:?: Ce treabă are COM1 cu COM2?

:!: COM1 și COM2 sunt legate împreună printr-un pipe al mașinii virtuale. Un write pe COM1 va scrie date care vor ajunge pe COM2 (pentru read)

2 - Funcții blocante

Context

:?: Ce înseamnă că read și write trebuie să fie blocante?

:!: Read trebuie să se blocheze dacă nu există date de citit (bufferul pentru read este gol) până când vin date (prin citire de pe port), și write trebuie să se blocheze dacă nu este spațiu de scris în bufferul de write până când se eliberează o parte din el (prin scriere pe port).

3 - Două buffere

Context

:?: De ce am nevoie de două buffere, unul pentru read și unul pentru write?

:!: E nevoie de două buffere pentru fiecare device (deci 4 în total), având următoarele funcții:

  • Bufferul pentru operația read: scrii în acest buffer datele primite pe portul serial (luate cu inb în handlerul de întrerupere) și le iei din acest buffer și le scrii în bufferul din userspace (în funcția read a device-ului).
  • Bufferul pentru operatia write: scrii în el din bufferul din userspace (în funcția write a device-ului) și iei din el în handler-ul de întrerupere și scrii pe port (cu outb).

Nu se poate folosi același buffer pentru ambele operații având în vedere că se referă la date diferite, unul la datele scrise pe port și altul la datele citite de pe port, date care de obicei sunt diferite. Nu prea te interesează să citești de pe portul serial ce tocmai ai scris pe el, ci ce s-a scris la celălalt capăt.

4 - Întreruperile se opresc

Context

:?: Se generează doar una/câteva întreruperi apoi se opresc. Care ar fi motivul?

:!: În întrerupere trebuie neapărat să citești IIR, altfel nu se va genera ack pentru întreruperea în curs și nu o să mai primești întreruperi.

Întrebări specifice Linux

1 - Un handler pentru două întreruperi

Context

:?: În handler-ul pentru intrerupere

irqreturn_t my_irq_handler(int irq_no, void *dev_id)

putem să folosim dev_id astfel încât să refere serial[0] și serial[1] ? serial [0] de exemplu este :

err = request_irq(MY_IRQ1, my_irq_handler, IRQF_SHARED, "uart16550", &serial[0]);

:!: Poți să înregistrezi același handler pentru ambele întreruperi (și MY_IRQ1 și MY_IRQ2); spre exemplu:

request_irq(MY_IRQ1, my_irq_handler, IRQF_SHARED, "uart16550", &my_serial[0]);
request_irq(MY_IRQ2, my_irq_handler, IRQF_SHARED, "uart16550", &my_serial[1]);

În acest caz membrul dev_id va fi &my_serial[0] sau &my_serial[1], după cum s-a transmis întreruperea MY_IRQ1 sau MY_IRQ2.

2 - Aflarea adresei de bază

Context

:?: Cum am putea afla pt ce COM este întreruperea (adresa mai exact , adică 0x3f8 sau 0x2f8),fără să citim registrul IIR?

:!: Presupunând că ai înregistrat bine cele două întreruperi pentru același handler,

if (irq_no == MY_IRQ1) {
/* intrerupere COM1 -> base_port = 0x3f8 */
}
else {
/* intrerupere COM2 -> base_port = 0x2f8 */
} 

O alternativă ar fi câmpul dev_id care să fie pointer la o structură specifică fiecărui COM, unde se va găsi și adresa de bază

struct structura_mea *sm = (struct structura_mea *)dev_id;
sm->base;

3 - Legătura între read/write și întreruperi

Context

:?: Din câte am înțeles, în write copiez din userspace într-un write buffer local. Write Bufferul este scris pe serial cu outb în handlerul de intrerupere. În read copiez în userspace dintr-un read buffer local. Read bufferul este umplut cu date primite pe serială(inb) în handlerul de întrerupere. Cum se leagă exact funcțiile de read și write de întrerupere? Mie îmi intră o singură dată în întrerupere la inițializarea modulului.

:!: RDAI trebuie să fie activă cât timp buffer-ul de citire nu este plin. Funcția de read ar trebui să activeze RDAI după ce a luat date din buffer-ul de citire iar handler-ul de întrerupere să dezactiveze RDAI dacă buffer-ul de citire devine plin. THREI trebuie să fie activă cât timp buffer-ul de scriere nu este gol. Funcția de write ar trebui să activeze THREI după ce a pus date în buffer-ul de scriere iar handler-ul de întrerupere să dezactiveze THREI dacă buffer-ul de scriere devine gol.

4 - Buffer circular

Context

:?: Există vreo implementare de buffer circular în Linux?

:!: Da, detalii găsiți în următorul articol LWN

Întrebări specifice Windows

1 - KeSetEvent în întrerupere

Context

:?: Se poate apela KeSetEvent din handlerul întreruperii ?

:!: NU. Din documentația KeSetEvent: the caller can be running at IRQL ⇐ DISPATCH_LEVEL. Nu puteți folosi KeSetEvent dintr-un handler de întrerupere. Va trebui să planificați un DPC pentru acest lucru. Mai multe detalii despre IRQL puteți afla aici .

2 - ACPI

:?: Cum dezactivez ACPI?

:!: Go to Device Manager (Right Click on MyComputer → Properties → Hardware). Under Computer entry, right click on Standard PC → Disable)

3 - Dezactivare COM1 & COM2

:?: Cum dezactivez COM1 & COM2?

:!: Go to Device Manager (Right Click on MyComputer → Properties → Hardware). Under Ports (COM & LPT) entry, right click on COM1/COM2 → Disable)

so2/teme/tema2/faq.txt · Last modified: 2017/03/23 21:48 by adrian.stanciu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0