Avanti Indietro Indice

8. Appendice

8.1 Indirizzi

Esistono tre tipi di indirizzi: indirizzi nella memoria principale, indirizzi I/O e indirizzi di configurazione. Gli indirizzi di configurazione nel bus PCI costituiscono uno spazio di indirizzi separato proprio come fanno gli indirizzi I/O. Tranne per il caso complicato degli indirizzi di configurazione ISA, dove il fatto che un indirizzo nel bus sia o meno un indirizzo di memoria, un indirizzo di I/O o un indirizzo di configurazione dipende solo dal potenziale di tensione in altre linee (tracce) del bus.

Indirizzi di Configurazione del Bus ISA (Read-Port, ecc.)

Nel bus ISA, tecnicamente non c'è uno spazio di indirizzi di configurazione, ma c'è un modo speciale con il quale la CPU accede ai registri di configurazione PnP sulle schede PnP. Per questo scopo sono allocati 3 indirizzi di I/O. Non sono allocati 3 indirizzi per ognuna delle schede, ma 3 indirizzi condivisi da tutte le schede.

Questi 3 indirizzi sono chiamati read-port (porta di lettura), write-port (porta di scrittura) e address-port (posta di indirizzo). Ogni porta ha la dimensione di un solo byte. Ogni scheda PnP ha molti indirizzi di configurazione cosicché solamente questi 3 indirizzi non sono nemmeno sufficienti per i registri di una sola scheda. Per comunicare con una certa schede, è inviato a tutte le schede nella write-port un numero speciale assegnato alla scheda (handle). Dopo di che la sola scheda che rimane in ascolto è quella con quell'handle. Allora l'indirizzo del registro di configurazione (di quella scheda) è inviato nella address-port (di tutte le schede -- ma solamente una è in ascolto). La comunicazione successiva inizia con un registro di configurazione su quella scheda leggendolo dalla read-port oppure scrivendolo nella write-port.

La write-port è sempre a A79 e la address-port è sempre a 279 (hex). La read-port invece non è fissata ma è impostata da software di configurazione ad un qualche indirizzo che si suppone non entri in conflitto con nessun'altra scheda ISA. Se c'è un conflitto, cambierà l'indirizzo. Tutte le schede PnP saranno poi «programmate» con questo indirizzo. Quindi se diciamo si usa isapnp per impostare o verificare i dati della configurazione si deve conoscere l'indirizzo di questa read-port.

Intervalli di Indirizzi

Talvolta in questo documento il termine «indirizzi» è usato per intendere un intervallo contiguo di indirizzi. Poiché gli indirizzi sono dati in byte, un indirizzo singolo contiene solamente un byte, mentre l'I/O e la memoria principale ne hanno bisogno di molti di più. È quindi spesso usato un intervallo di diciamo 8 byte per gli indirizzi I/O mentre l'intervallo di indirizzi in memoria principale allocato ad un dispositivo è molto maggiore. Per una porta seriale (un dispositivo di I/O) è sufficiente specificare l'indirizzo di partenza dell'indirizzo I/O del dispositivo (ad esempio 3F8) in quanto è ben noto che l'intervallo di indirizzi per una porta seriale è di soli 8 byte. L'indirizzo di partenza è noto come «base address» (indirizzo base).

Spazio di Indirizzi

In ISA, per accedere sia allo «spazio» di indirizzi I/O che a quello di memoria (principale) è usato lo stesso bus indirizzi (address bus) (le linee usate nel bus sono condivise). Come fa un dispositivo a sapere quando un indirizzo che appare sull'address bus è un indirizzo di memoria o un indirizzo I/O? Beh, ci sono 4 linee dedicate sul bus che trasportano questa informazione ed altro. Se una ben determinata di queste 4 linee è «attiva», dice che la CPU vuole leggere da un indirizzo I/O e quindi la memoria principale ignora l'indirizzo sul bus. Le altre 3 linee servono per scopi analoghi. In breve: esistono linee di lettura e di scrittura sia per gli indirizzi di memoria principale che per quelli di I/O (4 linee in tutto).

Nel bus PCI c'è la stessa idea di base, che usa sempre 4 linee, ma il tutto viene fatto in maniera un po' diversa. Invece di essere «attiva» solo una delle 4 linee, in queste viene posto un numero binario (16 diverse possibilità). Quattro di questi 16 numeri servono gli spazi di I/O e di memoria come visto prima. Inoltre c'è anche uno spazio di indirizzi di configurazione che usa altri 2 numeri. Gli altri 10 numeri extra sono lasciati per altri scopi.

Verifica dell'Intervallo (Test ISA per i Conflitti di Indirizzo I/O)

Nel bus ISA, c'è un metodo costruito dentro ogni scheda PnP per verificare che non ci siano altre schede che usano gli stessi indirizzi. Se due o più schede usano gli stessi indirizzi I/O, probabilmente neanche una scheda funzionerà bene (se non tutte). Un buon software di PnP dovrebbe assegnare le risorse-bus in modo da evitare i conflitti, ma anche in questo caso una scheda legacy potrebbe nascondersi da qualche parte lo stesso indirizzo.

Il test inizia con una scheda che mette un numero di controllo nei proprio registri I/O. Successivamente il software PnP lo legge e verifica di aver letto lo stesso numero di controllo. Se non è vero, qualcosa è andato storto (ad esempio un'altra scheda con lo stesso numero di controllo). Ripete allora lo stesso test con un altro numero di controllo. Poiché in realtà verifica l'intervallo di indirizzi I/O assegnati alla scheda, è detto «range check» (verifica di intervallo). Un nome migliore potrebbe essere verifica dei conflitti di indirizzo. Se c'è un conflitto di indirizzo si ottiene un messaggio d'errore e lo si deve risolvere per proprio conto.

Comunicare Direttamente Attraverso la Memoria

Tradizionalmente, la maggior parte dei dispositivi I/O usano solamente la memoria I/O per comunicare con la CPU. Per esempio, la porta seriale lo fa. Il device driver, in esecuzione nella CPU, vorrebbe leggere e scrivere dati sia dallo/nello spazio di indirizzi I/O che dalla/nella memoria principale. Il modo più veloce si avrebbe se il dispositivo stesso mettesse i dati direttamente nella memoria principale. Un modo per farlo è usare i Canali DMA o il «bus mastering». Un altro modo è di allocare al dispositivo un po' di spazio in memoria principale. In questo modo il dispositivo legge e scrive direttamente nella memoria principale senza preoccuparsi di DMA e bus mastering. Tale dispositivo può usare anche indirizzi I/O.

8.2 Interrupt -- Dettagli

Gli interrupt trasportano un sacco di informazioni, ma solo indirettamente. Il segnale di interrupt (una tensione in una linea) dice semplicemente ad un chip chiamato interrupt controller («controllore delle interruzioni») che un certo dispositivo chiede un po' di attenzione. L'interrupt controller allora lo segnala alla CPU. La CPU trova il driver per questo dispositivo e esegue una parte di esso nota come «interrupt service routine» (routine di servizio dell'interrupt) o «interrupt handler». Questa «routine» prova a capire cos'è successo e poi si occupa del problema, come il trasferimento di dati da (o nel) dispositivo. Questo programma (routine) può facilmente scoprire cos'è successo in quanto il dispositivo ha dei registri ad un indirizzo noto al software di gestione (premesso che le informazioni sul numero IRQ e l'indirizzo di I/O siano impostate correttamente). Questi registri contengono informazioni sullo stato del dispositivo. Il software legge il contenuto di questi registri e ispezionandone il contenuto, scopre cos'è successo e intraprende l'azione appropriata.

Quindi ogni device driver ha bisogno di sapere su quale numero di interrupt (IRQ) restare in ascolto. Nel bus PCI (e per le porte seriali sul bus ISA a partire dal kernel 2.2) è permesso che due (o più) dispositivi condividano lo stesso numero IRQ. Quando avviene tale interrupt, la CPU esegue la routine di servizio dell'interruzione per tutti questi dispositivi che usano quell'interrupt. La prima cosa che fa la prima delle routine è di controllare per vedere se l'interrupt è effettivamente avvenuto per il suo dispositivo. Se non c'erano interrupt (falso allarme) la routine termina e parte la successiva routine di servizio, ecc.

8.3 Interrupt PCI

Gli interrupt PCI sono diversi, ma poiché solitamente sono mappati su IRQ si comportano quasi nello stesso modo. Una differenza sostanziale è che gli interrupt PCI possono essere condivisi. Per esempio l'IRQ5 può essere condiviso da due dispositivi PCI. Questa funzionalità di condivisione è automatica: non è necessario hardware o software speciale. Si sono avute notizie di situazioni nelle quali questa condivisione non funzionava, ma solitamente era dovuto a difetti nel software di gestione del dispositivo. Si suppone che tutti i device driver per i dispositivi PCI forniscano la condivisione degli interrupt. Si noti che non è possibile condividere lo stesso interrupt tra il bus ISA e il bus PCI. Comunque, le condivisioni illegali funzioneranno a patto che i dispositivi in conflitto non siano in uso nello stesso istante. «In uso» qui significa che un è in esecuzione un programma che «apre» il device nel suo codice C di programmazione.

È necessario conoscere alcuni dettagli del sistema di interrupt PCI per poter impostare il CMOS del BIOS o i ponticelli nelle vecchie schede PCI. Ogni scheda PCI ha 4 possibili interrupt: INTA#, INTB#, INTC# e INTD#. Quindi per un sistema a 7 slot ci possono essere 7 x 4 = 28 diverse linee di interrupt. Ma le specifiche permettono un numero minore di linee di interrupt. Questo non è troppo restrittivo in quanto gli interrupt possono essere condivisi. Molti bis PCI sembrano essere fatti con solo 4 linee di interrupt. Chiamiamole linee (connessioni o tracce) W, X, Y e Z. Supponiamo di progettare l'interrupt B dello slot 3 come interrupt 3B. Allora la linea W potrebbe essere usato per condividere gli interrupt 1A, 2B, 3C, 4D, 5A, 6B e 7C. Ciò è fatto connettendo fisicamente la linea W alla linee 1A, 2B, ecc. Nello stesso modo la linea X potrebbe essere connessa alle linee 1B, 2C, 3D, 4A, 5B, 6C e 7D. Poi, all'avvio, il BIOS mappa le linee X, W, Y e Z su IRQ. Dopodiché scrive l'IRQ sul quale è mappato ogni dispositivo dentro un registro hardware presente su ogni dispositivo. Ora chiunque interroghi il dispositivo può trovare quale IRQ usa.

Le summenzionate linee X, W, Y e Z sono etichettate nelle specifiche PCI come INTA#, INTB#, INTC# e INTD#. Questa notazione PCI ufficiale può confondere in quanto ora INTA# ha due possibili significati a seconda si stia parlando di uno slot o del bus PCI. Per esempio, se 3C è mappato su X allora diciamo che l'INTC# dello slot 3 è connesso a INTA# (X) del bus PCI. Notazione piuttosto confusa.

Inoltre c'è un altro vincolo. Uno slot PCI deve usare per primo l'interrupt con la lettera più bassa. Quindi se una slot usa solo un interrupt, deve essere INTA#. Se ne usa due devono essere INTA# e INTB#, ecc. Una scheda in uno slot può avere su fino ad 8 dispositivi, ma per questi ci sono solo 4 interrupt PCI. Ciò va bene lo stesso in quanto gli interrupt possono essere condivisi in modo tale che ognuno degli 8 dispositivi (se esistono) può avere un interrupt. La lettera dell'interrupt PCI di un dispositivo spesso è fissa e scritta nell'hardware del dispositivo.

Il BIOS assegna IRQ (interrupt) in modo da evitare i conflitti con gli IRQ che sa sono già assegnati sul bus ISA. Talvolta nel menu CMOS del BIOS è possibile assegnare gli IRQ alle schede PCI (ma non è così semplice come spiegato sopra). Ci sono situazioni nelle quali Windows azzera tutti i numeri IRQ delle schede PCI dopo l'impostazione della mappatura degli IRQ. Se poi qualcuno avvia Linux da Windows ottiene come risultato che Linux può trovare solo IRQ nulli e quindi sbagliati.

Si potrebbe pensare che poiché il PCI sta usando gli IRQ (il bus ISA) potrebbe essere lento, ecc. Non in realtà. I chip ISA di controllo degli interrupt posseggono linee dirette di interrupt che vanno alla CPU in modo da ottenere attenzione immediata. Mentre i segnali nei bus ISA di dati e indirizzi devono passare per il bus PCI per ottenere la CPU, i segnali di IRQ ci vanno direttamente.

8.4 Isolamento

Questa cosa è pertinente solo con il bus ISA. L'isolamento («isolation») è un complesso metodo per assegnare un handle temporaneo (numero identificativo o Card Select Number = CSN) ad ogni dispositivo PnP presente nel bus ISA. Sebbene esistano modi molto più efficienti (ma più complessi) per fare questa cosa, alcuni dicono che questo è un metodo semplice. È usato solo un indirizzo di scrittura per tutte le scritture PnP a tutti i dispositivi PnP, cosicché quello che viene scritto in questo indirizzo va a tutti i dispositivi PnP che sono in ascolto. Questo indirizzo di scrittura è usato per inviare (assegnare) un handle univoco ad ognuno dei dispositivi PnP. Questa assegnazione richiede che solo un dispositivo sia in attesa quando è inviato (scritto) l'handle in questo indirizzo comune. Tutti i dispositivi PnP hanno un numero di serie univoco che usano per il processo di isolamento. Fare l'isolamento è qualcosa di simile ad un gioco. È fatto usando l'equivalente di una sola linea del bus che collega tutti i dispositivi PnP e il programma di isolamento.

Nel primo giro di questo «gioco» tutti i dispositivi PnP sono ascolto su questa linea e inviano simultaneamente una sequenza di bit nella linea. I bit permessi sono un «1» (tensione positiva) oppure uno «0 aperto» di nessuna tensione (circuito aperto e tri-state). Ogni dispositivo PnP inizia semplicemente ad inviare sequenzialmente su questa linea il suo numero di serie, bit a bit, iniziando con il bit più significativo. Se un qualsiasi dispositivo, invia un 1, un 1 sarà sentito sulla linea da tutti gli altri dispositivi. Se tutti i dispositivi inviano uno «0 aperto» nella linea non si sentirà niente. L'obbiettivo è di eliminare (alla fine di questa prima tornata) tutti i dispositivi tranne quello con il numero di serie più elevato. «Eliminato» significa che cessa restare in ascolto all'indirizzo di scrittura al quale restano in ascolto tutti i dispositivi ancora in gioco. Ciò è detto anche «dropping out». (Si noti che tutti i numeri di serie sono della stessa lunghezza.)

Per prima cosa si consideri solo il bit più significativo del numero di serie che viene posto per primo sulla linea da tutti i dispositivi che non hanno ancora un handle. Se un qualsiasi dispositivo PnP invia uno 0 (0 aperto) ma sente un 1, questo significa che qualche altro dispositivo PnP ha un numero di serie più alto, e quindi temporaneamente si toglie dal gioco e non ascolta più finché il giro non è terminato (ovvero quando viene assegnato un handle al vincitore: il dispositivo con il numero di serie più alto). Ora i dispositivi ancora in gioco hanno tutti il medesimo bit più significativo (un 1), e quindi, per la partecipazione futura a questo giro, possiamo trascurare questa cifra e considerare solo la parte restante del numero di serie. Adesso si torni all'inizio di questo paragrafo e lo si ripeta finché per tutti i dispositivi non siano stati esaminati completamente i numeri di serie (si veda sotto per il caso di tutti 0).

Quindi è chiaro che il numero di serie più alto non verrà eliminato dal gioco. Ma cosa succede se le cifre più significative (anche nel caso dei numeri di serie ridotti) sono tutte 0? In questo caso è stato inviato uno «0 aperto» nella linea e tutti i partecipanti rimangono in gioco. Se tutti hanno uno 0 come cifra più significativa allora gli 0 sono trascurati come è stato fatto nel paragrafo precedente con gli 1. Il gioco continua inviando la cifra successiva del numero di serie.

Alla fine di questa tornata (dopo che ogni partecipante rimasto ha inviato il bit meno significato del numero di serie) rimane solo il dispositivo PnP con il numero di serie più elevato. A questo viene assegnato un handle ed esce permanentemente dal gioco. Poi tutti quelli scartati precedentemente rientrano in gioco e inizia un nuovo giro con un partecipante in meno. Alla fine, viene assegnato un handle a ciascun dispositivo PnP. È facile vedere che questo algoritmo funziona.

Una volta assegnati, gli handle sono usati per indirizzare ogni dispositivo PnP, sia per potergli inviare una configurazione sia per leggere le informazioni di configurazione dal dispositivo stesso. Si noti che questi handle sono usati solo per la configurazione PnP e non sono usati per le normali comunicazioni con il dispositivo. Quando il computer viene avviato, tutti gli handle sono stati persi e quindi il BIOS PnP solitamente opera il processo di isolamento ogni qualvolta si riavvia il proprio PC.

FINE DEL Plug-and-Play-HOWTO


Avanti Indietro Indice