heuer möchte ich meine niegelnagelneue video blaster plus karte an einen
avr anschließen. einen beispielhaften source code für alte isa pcs hab
ich schon gefunden. allerdings hab ich noch ein paar fragen zum isa
bus.
wofür sind die aen (A11) und ale (B28) signale gedacht?
wie ist das mit dem /refresh (B19)?
(auf der karte sind 1 mb drams, die /refresh leitung verschwindet
irgendwo unter einem F82C9001A)
was mach ich mit /sbhe (C1) und /memcs16 (D1)?
Da kann ich Dir nur einen Artikel aus c't 11/91, S.336 nahelegen.
Oder -falls da noch irgendwie 'ranzukommen ist- eine Norm namens IEEE
P996.
Hier mal ein Auszug:
AEN (a11) | O | Address Enable | offen
AEN untersteht bei ISA allein dem DMA-Controller. Bei einem
DMA-Transfers ist es den ganzen Zyklus über high (100 ns vor /BALE- bis
30 ns nach /COMMAND+), und sorgt so dafür, daß sich I/O-Ports nicht
versehentlich angesprochen fühlen (alle Peripheriekarten müssen AEN
auskodieren).
Bei EISA-Boards dient AEN zusätzlich einer geographischen Adressierung.
Das heißt, jeder Slot hat im 16bittigen I/O-Adreßraum einen eigenen
individuellen Adreßbereich. Nur dieser Slot bekommt bei Portzugriffen
AENx inaktiv low geliefert, alle anderen sind durch AENx high
abgehängt. AEN ist von EISA demnach zu einem Slot-Select für I/O
umfunktioniert worden. Die kompatiblen Adressen und DMA-Transfers sind
jedoch alle AENx gleichgeschaltet zum kompatiblen AEN.
Busmaster-Zugriffe sind trotz der Sekundanz des DMA-Controllers wie
CPU-Zugriffe definiert (nur mit /BALE high). AEN ist daher die
Zyklusdauer über low.
BALE (b28) | O | Bus Address Latch Enable | offen
BALE- zeigt an, daß nun die `gelatchten´ Adressen SA0 ... SA19, AEN und
/SBHE gültig sind. Diese sind dazu mindestens 29 ns vor BALE- auf den
Bus zu legen. Minimaldauer von BALE: 50 ns. Während eines DMA-Transfers
oder Busmaster-Zugriffs muß BALE für den gesamten Zyklus high sein.
/REF (b19) | I/O | Refresh | 4,7 KOhm (E-ISA: 300 Ohm)
Im alten PC wurde der DMA-Kanal 0 für den Refresh miß- braucht.
Folglich fand man auf b19 auch /DACK0 als Hinweis dafür, daß auf der
Hauptplatine gerade ein Refresh im Gang ist. Beim AT hat man hierhin
das entsprechende Signal des Refresh-Controllers gelegt und /DACK0 nach
d8 verlagert.
Wenn /REF nach low geht, kann externe Speicherperipherie zusammen mit
dem Hauptspeicher einen Refresh einleiten. /REF- ist gleichzeitig mit
SA0...SA7 (E-ISA SA0...SA15) gültig, /MEMR folgt frühestens 114 ns
(E-ISA 120 ns) später und bleibt mindestens 214 ns (E-ISA 235 ns)
aktiv. Durch /IOCHRDY läßt sich der Zyklus verlängern, aber nicht durch
/0WS verkürzen. Zu beachten ist, daß bei ISA laut Spezifikation nur
SA0...SA7 anliegen müssen, das reicht nicht für die 4-MBitter, die 1024
Refresh-Adressen benötigen.
/SBHE (c1) | I/O | System Bus High Enable | offen
/SBHE ist immer aktiv, wenn Daten über die oberen Datenleitungen
SD8...SD15 zu transportieren sind (sowohl bei Zugriffs- wie bei
Transferzyklen). Im Timing ist es identisch mit SAx. Seine Bedeutung im
Zusammenspiel mit SA0, /MEMCS16 und den Daten ist unter SDx aufgeführt.
/MEMCS16 (d1) | I/(O) | Memory Chip Select 16 Bit | 300 Ohm
/MEMCS16 ist das Rückmelde-Signal, welches die Peripherie `rechtzeitig´
zurückmelden muß, wenn sie bei Memory-Zugriffszyklen 16bittig bedient
werden möchte. Rechtzeitig stehen dazu beim Original-AT nur die frühen
ungelatchten Adressen LA17...LA23 zur Verfügung, so daß eine Karte
immer gleich 128 KByte zum 16-Bit-Bereich erklären muß, selbst wenn sie
etwa nur 16 KByte Adreßraum belegt.
Sollte sich im betroffenen 128-KByte-Bereich irgendwo 8bittiger
Speicher befinden (VGA, Netzwerkkarte, SCSI ....), wird dieser
unweigerlich mit der falschen Datenbreite angesprochen =>
$>&%>$´$%$>%!!!
Um das Problem zu umschiffen, ziehen viele moderne 16-Bit-Karten daher
die späten SAx-Adressen in die Dekodierung mit ein. Mit einem schnellen
Decoder hoffen sie, daß das /MEMCS16 noch früh genug kommt. Bei einem
Original-AT hätten sie damit kaum eine Chance, die neueren Chipsätze
sind jedoch im Timing wesentlich toleranter, so daß sie im Regelfall
Erfolg haben.
Leider haben sowohl IEEE wie EISA in dieser Beziehung eine saubere
Spezifikation versäumt! Schlimmer noch, zumindest in [1] wird /MEMCS16
im Timing-Diagramm völlig falsch dargestellt, so daß der
Fehlinterpretation Tür und Tor geöffnet ist. LAx muß bei CPU-Zyklen
minimal 100 ns (E-ISA: 116 ns) vor BALE- und /MEMCS16- maximal 80 ns
(96 ns) nach LAx aktiv sein, mithin also /MEMCS16- mindestens 20 ns vor
BALE-.
Es fehlt eine Spezifikation der Minimalzeit von SAx zu /MEMCS16-. So
bleibt es nach wie vor im Belieben der Chipsatz-Hersteller, ob die
exakte Dekodierung via SAx einfach möglich ist, mit
Hochgeschwindigkeits-Decodern oder überhaupt nicht.
Da /MEMCS16 allein auf Adressen (egal ob Memory oder I/O, Refresh oder
floatend) reagiert, wird es mitunter auch `unmotiviert´ bei anderen
Zugriffen, etwa bei I/O aktiv. Die Buslogik darf sich dadurch nicht
irritieren lassen. Allerdings wird dadurch das Timing etwas enger. Wenn
noch /MEMCS16 aktiv ist und ein 8-Bit-Zugriff ansteht, verbleiben wegen
der langen Rise-Time nur 66 ns (gegenüber sonst 80 ns), um es zu
desaktivieren.
Bei Busmaster-Zugriffen auf den Hauptspeicher ist darauf zu achten, daß
der Original-AT und seine Kompatiblen völlig regelwidrig kein
/MEMCS16-Signal liefern, das ist nur für EISA-Boards Pflicht. Leider
hat IEEE dies nicht auch den ISAs auferlegt, so daß hier die nächste
Konfliktsituation vorprogrammiert ist. Busmaster müssen daher /MEMCS16
weitgehend ignorieren und müssen spekulieren:
Adresse /Memcs16 vermutete Breite
> 1MB x 16 Bit
< 640KB x 16 Bit
640KB-1MB 0 16 Bit
1 8 Bit
Die ersten beiden Annahmen sind völlig gerechtfertigt, es wird kaum
`ATs´ mit 8bittigem Hauptspeicher geben oder Peripherie mit 8bittigem
Extended Memory (obwohl beides nicht 100prozentig verboten ist). Die
dritte mit /MEMCS16 ist eindeutig, nur die vierte steht auf wackligen
Füßen. Sollte Shadow-RAM oder Speicher zwischen den Adaptern
eingeblendet sein und Board/Chipsatz kein /MEMCS16-Signal zurückliefern
- wie es bei den meisten (NEAT, HT21, TopCat etc.) üblich ist -, so
könnte sich der Busmaster vertüddeln.
So verzichten übliche Busmaster lieber ganz auf 8-Bit-Zugriffe und
ignorieren /MEMCS16 völlig. Das gibt dann Trouble, wenn etwa aufs
8bittige Video-RAM oder eine 8-Bit-Speicherkarte (c´t-CMOS-RAM-Karte)
zugegriffen wird.
Bei DMA-Transfers über einen 16-Bit-Kanal (DRQ5...7) wird /MEMCS16
ignoriert, dafür sind sowohl der betroffene I/O-Port als auch der
Speicher 16bittig auzulegen. Anders verhält es sich bei den
8-Bit-Kanälen (DRQ0...3). Hier gilt nur für den I/O-Port die Pflicht,
8bittig zu sein, der Speicher darf beide Breiten haben. Bei 16 Bit muß
das /MEMCS16-Signal bedient und von der Buslogik ausgewertet werden (in
diesem Punkt ist übrigens Ed Solari [1] etwas widersprüchlich, so findet
man darüber auch keine Timing-Daten).
Hardware-Designer sollten den Pullup-Widerstand von 300 Ohm beachten,
der viele Standard-TTLs überfordert.
auhaueha!
ohweiohwei..
hmm ... denkdenk ...
/smem16 : ignorieren ich weiß eh dass der speicher der karte 16 bit
breit ist.
/sbhe : bei 8 bit io high ansonsten low
bale : kurz vor dem r/w zugriff auf high
aen : low
/ref : erstmal high
2*8 bit io + 8 bit adr + res + rd + wr + alel + aleh + /sbhe + bale
hui bleibt noch einer von 32 pins übrig. halb ausgegraben ist das board
jetzt schon. morgen werd ich dann anfangen es zu testen.
Hallo Rufus T. Firefly,
du hast scheinbas die spezifikationen. Kannst du sie nicht einfach hier
als dateianhang mit dranhängen, statt auf irgendwas zu verweisen?
Dazu müsste ich meine alte c't herauskramen, den Artikel (etliche
Seiten) scannen, in ein verständliches Format bringen und unter
Umgehung des Copyrights des Heiseverlages hier vervielfältigen.
Zwar liegt der Artikel auch in elektronischer Form vor (dazu gibt es ja
die c't-Jahres-CDs), darin aber fehlen so gut wie alle Abbildungen, und
das sind die zum Verständnis sehr wichtigen Timingdiagramme.
Von den juristischen Auswirkungen abgesehen, ist das einiges an Arbeit,
die ich mir nicht machen möchte. Mein Altruismus hat heute Urlaub.
Prinzipiell sollte man aber auch auf anderem Wege an diese
Spezifikation 'rankommen; der ISA-Bus lebt im PC104-Bus fort, und an
dessen Spezifikation gelangt man bei www.pc104.org.
Nicht sonderlich ausführlich, weil wiederum auf IEEE-P996 verwiesen
wird.
Google spuckt, damit gefüttert, zwar jede Menge Links aus, aber an die
offizielle Spezifikation kommt man so ohne weiteres nicht heran.
Das hier sollte einen aber auch weiterbringen:
http://www.techfest.com/hardware/bus/isa_sokos.htm
Diese Specs haben einige Klarheiten beseitigt.. Immerhin weiß ich jetzt
warum die RTL NE2000 Karte sowohl bei 0x0300 als auch bei 0xff00 ihre
Register einblendet.
Die Video Karte stellt sich aber leider trotzdem tot. Jedenfalls in
meinem Board. Unter DOS konnte ich mit dem mitgelieferten Debugger die
Register lesen und schreiben. Die Setup Sequenz sieht für den PC so
aus:
<code>
set_port_address:
mov dx,_config.wPortAddr ;Set Video Plus port address.
mov al,dl
out dx,al
mov ax,03FFh
out dx,ax ;Enable Video Plus.
inc dx
in al,dx ;Read chip version number.
shr al,4
xor ah,ah
mov _wVersion,ax
</code>
wie ist das jetzt genau bei "out dx, ax" geregelt? wird al oder ah
auf sd0-7 gelegt? ich vermute mal al. weil "mov ax, 1906h ; out dx,
ax" soll dann nämlich etwas später register 06h auf 19h setzen.
Außerdem steht in den docs das 0xad6 der register select port ist und
0xad7 der data port.
ich hab das nun soweit wie möglich anhand der Specs von oben auf meinen
Atmel übersetzt:
<code>
enable:
ldi XH, 0x0a ; default port address 0xad6
ldi XL, 0xd6
mov dl, XL
rcall out8
ldi dl, 0xff
ldi dh, 0x03
rcall out16
rcall in8
mov r16, dl
rcall txb
ret
out16:
push r16
ldi r16, 0x20 ; io select + /SBHE low
out PORTA, r16
ISA_AL2
pop r16
out PORTA, XH ; latch upper address
ISA_AL1
out PORTA, XL ; set lower address
ISA_ALE ; assert BALE
ISA_WR16 dl, dh
ret
out8:
push r16
ldi r16, 0x60 ; io select + /SBHE high
out PORTA, r16
ISA_AL2
pop r16
out PORTA, XH ; address latch
ISA_AL1
out PORTA, XL
ISA_ALE
ISA_WR8 dl
ret
in8:
push r16
ldi r16, 0x60 ; io select + /SBHE high
out PORTA, r16
ISA_AL2
pop r16
out PORTA, XH
ISA_AL1
out PORTA, XL
ISA_ALE
ISA_RD_START
ISA_RD8 dl
ISA_RD_STOP
ret
.equ ISA_CTRL = PORTD
.equ ISA_CTRL_DIR = DDRD
.equ ISA_ADDR = PORTA
.equ ISA_ADDR_DIR = DDRA
.equ ISA_DATA = PORTC
.equ ISA_DATA_IN = PINC
.equ ISA_DATA_DIR = DDRC
.equ ISA_DATB = PORTB
.equ ISA_DATB_IN = PINB
.equ ISA_DATB_DIR = DDRB
.macro ISA_AL2
; latch a16-a19 (bits 0-3), mem toggle (4), io select (5), /sbhe (6),
reset (7)
sbi ISA_CTRL, PD5
cbi ISA_CTRL, PD5
.endmacro
.macro ISA_AL1
; latch a8-a15
sbi ISA_CTRL, PD4
cbi ISA_CTRL, PD4
.endmacro
.macro ISA_ALE
; toggle BALE
sbi ISA_CTRL, PD6
cbi ISA_CTRL, PD6
.endmacro
.macro ISA_WR8
out ISA_DATA, @0
sbi ISA_CTRL, PD2
nop
cbi ISA_CTRL, PD2
.endmacro
.macro ISA_WR16
out ISA_DATA, @0
out ISA_DATB, @1
sbi ISA_CTRL, PD2
nop
cbi ISA_CTRL, PD2
.endmacro
.macro ISA_RD_START
out ISA_DATA_DIR, reg00
out ISA_DATB_DIR, reg00
out ISA_DATA, regff
out ISA_DATB, regff
.endmacro
.macro ISA_RD_STOP
out ISA_DATA_DIR, regff
out ISA_DATB_DIR, regff
.endmacro
.macro ISA_RD8
sbi ISA_CTRL, PD3
nop
in @0, ISA_DATA_IN
cbi ISA_CTRL, PD3
.endmacro
.macro ISA_RD16
sbi ISA_CTRL, PD3
nop
in @0, ISA_DATA_IN
in @1, ISA_DATB_IN
cbi ISA_CTRL, PD3
.endmacro
</code>
Die Macros hab ich mit zwei NE2000 Karten verifiziert bei 4 und 16 MHz.
Bei 16 Mhz genügt ein nop. Die Video Karte funktioniert auch mit 4 wait
states nicht. So ein Mist!