This is an old revision of the document!


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 citite de pe port(bufferul pentru read este gol) până când vin date, și write trebuie să se blocheze dacă nu ai 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 pt intrerupere

irqreturn_t my_handler(int irq_no,void *dev_id,struct pt_regs *regs)

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_handler,SA_INTERRUPT,"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_handler,SA_INTERRUPT,"uart16550",&my_serial[0]);
request_irq(MY_IRQ2,my_handler,SA_INTERRUPT,"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.

:!: La sfârșitul fiecărei funcții write va trebui fie să reactivați întreruperile

outb(0x00, IER); outb (0x03, IER);

fie activați întreruperea de empty buffer doar când există ceva în buffer-ul device-ului de scris.

4 - Buffer circular

Context

:?: Există vreo implemente 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 - Cum dezactivez ACPI?

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

=== 3 - 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.1360455039.txt.gz · Last modified: 2013/03/30 16:20 (external edit)
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