EMS 3.2 unter DOS (<= 286)

Konfiguration, Anwendungen, Treiber und TSRs unter DOS
mkarcher
LAN Manager
Beiträge: 204
Registriert: Fr 5. Jun 2020, 19:38

Re: EMS 3.2 unter DOS (<= 286)

Beitrag von mkarcher »

Was Du schreibst, ergibt Sinn. Es fehlt hier die Garantie, dass A8..A19 gültig sind, und falls die Leitungen dank tristate irgendwo in der Luft hängen, könnten sich mehrere Karten angesprochen fühlen, die dann einen gelesenen Wert auf den ISA-Bus geben würden. Deshalb ist es eine gute Idee, /OE vom Daten-Treiber/Level-Shifter so zu behandeln, dass der bei /REFRESH Ruhe gibt.

Ich habe allerdings gerade mal zwei Karten mit BIOS angeschaut, einen AHA-1505 (BIOS nicht bestückt) oder so und einen billigen NE2000-Klon. Beide reagieren für BIOS-Zugriffe auf ISA-Memory-Reads, aber keine von diesen Karten belegt /REFRESH. Man kommt also in der Praxis ohne Berücksichtigung von /REFRESH aus, auch wenn das anscheinend gegen die Spezifikation verstößt. Auch IBMs originale MDA und CGA-Karte berücksichtigen /REFRESH nicht. Dadurch gibt es meines Erachtens genügend Präzedenzfalle, dass die Nicht-Beachtung von /REFRESH in der Praxis wirklich unproblematisch ist, auch in ganz alten PC-kompatiblen Computern.
Jackintosh
MemMaker-Benutzer
Beiträge: 57
Registriert: Di 25. Okt 2022, 15:46

Re: EMS 3.2 unter DOS (<= 286)

Beitrag von Jackintosh »

Einen 74LVC1G00 habe ich mal vorgesehen. Ich setze mal Lötbrücken daneben, um die ursprüngliche Schaltung ohne /REFRESH Auswertung auch zu ermöglichen. Layout wird (mal wieder) herausfordernd. PCBs bestelle ich im Winter, wenn einige Layouts zusammengekommen sind. Für ST/STE habe ich da auch noch einiges zu tun.

Eine Frage noch: auf Systemen, bei denen die CPU mit < 8MHz getaktet wird, läuft der ISA im gleichen Takt (d.h. der BLCK auf B20)?
Da ich den 74LVC4040 als RefreshTimer mit diesem Takt füttere und er den Refresh-Pin für 8MHz aktiviert, ist das nicht ganz unwichtig. Sonst leidet das SDRAM u.U. an Alzheimer.
mkarcher
LAN Manager
Beiträge: 204
Registriert: Fr 5. Jun 2020, 19:38

Re: EMS 3.2 unter DOS (<= 286)

Beitrag von mkarcher »

Jackintosh hat geschrieben: Mi 2. Nov 2022, 09:14 Eine Frage noch: auf Systemen, bei denen die CPU mit < 8MHz getaktet wird, läuft der ISA im gleichen Takt (d.h. der BLCK auf B20)?
Da ich den 74LVC4040 als RefreshTimer mit diesem Takt füttere und er den Refresh-Pin für 8MHz aktiviert, ist das nicht ganz unwichtig. Sonst leidet das SDRAM u.U. an Alzheimer.
Üblicherweise ja. Und ich bin mir ziemlich sicher (auch wenn ich es nicht gemessen habe), dass mein Turbo-XT im Turbo-Modus BCLK mit 10MHz laufen lässt. Also musst Du schon mal mit allem zwischen 4,77 und 10MHz rechnen, auch wenn nach IEEE meines Wissens nach nur 6 bis 8.33 zulässig ist. Auf 33MHz-Computern den ISA mit 33/3 = 11 statt 33/4 = 8.33 laufen zu lassen, war auch Volkssport.

Wenn Du einen verlässlichen Takt brauchst, ignore BCLK, und nimm OSC. Das sind immer 14.318 MHz bis auf ein ganz paar Exoten-PCs, in denen dann einige Karten sich sehr seltsam verhalten würden.
Jackintosh
MemMaker-Benutzer
Beiträge: 57
Registriert: Di 25. Okt 2022, 15:46

Re: EMS 3.2 unter DOS (<= 286)

Beitrag von Jackintosh »

Ich bleibe erstmal bei BCLK und sehe am 4040 Zähler folgendes vor: momentan geht (ohne jetzt nachgesehen zu haben) Q7 als Refresh-Flag ans CPLD. Ich setze einen 3pin Jumper neben den 4040 und gebe Q6 und Q7 auf die äußeren Pins. Der mittlere geht dann als Refresh-Flag ans CPLD. Momentan kommen sowieso zuviele Refreshs, aber lt. meinen Messungen am ST hat das keine Nachteile auf die Performance. Es wird somit erst zum Problem, wenn BLCK deutlich unter 4MHz fällt.
Aber bevor es ans Layout geht, schreibe ich erstmal den VHDL Code und schaue, ob das alles überhaupt rein passt.
mkarcher
LAN Manager
Beiträge: 204
Registriert: Fr 5. Jun 2020, 19:38

Re: EMS 3.2 unter DOS (<= 286)

Beitrag von mkarcher »

Jackintosh hat geschrieben: Do 3. Nov 2022, 11:40 Ich bleibe erstmal bei BCLK und sehe am 4040 Zähler folgendes vor: momentan geht (ohne jetzt nachgesehen zu haben) Q7 als Refresh-Flag ans CPLD.
Also nutzt du 8MHz durch 128, also etwa alle 16µs einen Refresh (oder alle 32µs bei 4MHz Bustakt). In den Zusammenhang erinnere ich Dich dann noch mal an die /REFRESH-Leitung, wo Du alle 16µs einen Puls bekommst (oder möglicherweise alle 64µs wenn irgendwer im CMOS-Setup "slow refresh" eingestellt hat). Wenn Du den Refresh an diese Leitung koppelst, kannst Du Dir möglicherweise sogar den 4040 sparen - es sei denn, Du brauchst den als Adress-Zähler. Ich meine mich aber zu erinnern, dass SDRAM, genauso wie klassisches RAM beim CAS-before-RAS-Modus, einen internen Refresh-Adress-Zähler hat, und man nur für ausreichend viele Refresh-Zyklen sorgen muss.
Jackintosh
MemMaker-Benutzer
Beiträge: 57
Registriert: Di 25. Okt 2022, 15:46

Re: EMS 3.2 unter DOS (<= 286)

Beitrag von Jackintosh »

SDR-SDRAMs benötigen lt.Datenblatt auch eine StartUp-Delay von ~200µs. Dafür nehme ich den Q11 Ausgang des 4040, d.h. bei 8MHz kommt der alle 256µs. Das passt dann auch noch für 10MHz BCLK.
Habe gestern mal alles in eine *.vhdl gepackt und es passt nicht mehr ins CPLD rein. Ich müsste somit auf das nächst größere Modell ausweichen, das dann in einem TQFP144 daherkommt und deutlich mehr kostet.
Die Adresspins sind dem SDRAM während des Refreshs egal. Es gibt ein spezielles Resresh-Kommando, das ich äquidistant ausführe und das immer Vorrang for R/W Kommandos hat. Habe eben nochmal nachgeschaut und dieses SDRAM will sogar alle 32ms 8K Refreshs haben - also etwa alle 4µs. Muss ich die Anschlüsse am 4040 nochmal umsortieren.
Für den ST habe ich auch eine RAM-Erweiterung mit PS/2 SIMM gebaut. Da nutze ich einen CBR-Refresh und die Adresspins sind dann ebenfalls egal.

Ich habe mir Deine Flip-Flop-Minimierungsidee zu Gemüte geführt und bin mit diesem Code herausgekommen. Ich weiß nicht, ob es das ist, was Du meintest. Da ich nicht weiß, in wie weit Du VHDL lesen kannst, erläutere ich mal kurz:
  • In der entity definiere ich die Signale: den ISA-Adressbus und /BALE.
  • In der architecture definiere ich einen Aufzählungstyp MEMORY_TYPE, der drei Werte annehmen kann (EMS, UMB und kein Speicher). Dies ist der Rückgabewert der folgenden Funktion.
  • CheckAddressRange() bekommt als Parameter /BALE und die oberen sechs Bit des Adressbusses.
  • Ich lege zwei lokale Variablen an: den Rückgabewert und eine 20Bit Vergleichsmaske.
  • Wenn /BALE = low und A19 = high, dann wird in den folgenden Anweisungsblock verzweigt.
  • Die Vergleichsbitmaske wird gelöscht.
  • Nun kommt ein großes switch/case (wie in C)
  • Je nachdem, welche Bitmaske in A18..A14 steht, wird eines der Bits in COMPARE_BITMASK gesetzt.
  • In REGISTER_EMS und REGISTER_UMB wird von der Config-SW eingetragen, welche auf 16KB ausgerichteten Blöcke entweder UMB oder einen der vier EMS Frames darstellen. Für jeden 16KB Block ein Bit. $A0000..$A3FFF entspricht Bit 19 usw.
  • Mit if((COMPARE_BITMASK & REGISTER_EMS) != 0) (in C) prüfe ich, ob ein EMS-Frame adressiert wird. Dito für UMB und liefere dann einen Wert vom Typ MEMORY_TYPE zurück.
Nun weiß ich zwar, daß u.U. EMS oder UMB adressiert werden, aber ich weiß nicht exakt welcher Block/Frame. Was ich suche, ist eine platzsparende Idee, wie ich von der Bitmaske auf eine Adressvergleichsmaske komme. Also etwas, das ich mit den Adressbits 19..14 auf dem ISA vergleichen kann, ohne zu rechnen (hier wohl Addition).
Plan B ist, die vier Frames an einer 64K Adresse auszurichten. Dann muss ich nicht rechnen.

Code: Alles auswählen

entity EMS is
	port(
		ISA_ADDR			: in std_logic_vector(19 downto 0); 		-- ISA address bus
		ISA_BALE			: in std_logic								-- ISA /BALE
   );
end entity;

architecture Behaviour of EMS is
	subtype  MEMORY_TYPE is unsigned (1 downto 0);
	constant MEMORY_NONE		: MEMORY_TYPE := "00";
	constant MEMORY_EMS		: MEMORY_TYPE := "01";
	constant MEMORY_SRAM		: MEMORY_TYPE := "10";

	signal	 REGISTER_EMS		: std_logic_vector(19 downto 0);	-- EMS Frame anywhere on 16KByte aligned address $A0000..$E0000 | 1Bit for each 16KB frame
	signal	 REGISTER_UMB		: std_logic_vector(19 downto 0);	-- UMBs anywhere on 16KByte aligned address $A0000..$EFFFF  | 1Bit for each 16KB frame

	-- ***************************************************************************
	--                             Address range checks
	-- ***************************************************************************
	impure function CheckAddressRange(ISA_BALE : std_logic; ISA_ADDR : std_logic_vector(19 downto 14)) return MEMORY_TYPE is
	variable	Result			: MEMORY_TYPE;
	variable	COMPARE_BITMASK	: std_logic_vector(19 downto 0);
	begin
		Result := MEMORY_NONE;
		if (ISA_BALE = '0') and (ISA_ADDR(19) = '1') then
			COMPARE_BITMASK	:= (others => '0');
			case ISA_ADDR(18 downto 14) is
				when "01000" => COMPARE_BITMASK(19) := '1';		-- $A0000..$A3FFF UMA
				when "01001" => COMPARE_BITMASK(18) := '1';		-- $A4000..$A7FFF UMA
				when "01010" => COMPARE_BITMASK(17) := '1';		-- $A8000..$ABFFF UMA
				when "01011" => COMPARE_BITMASK(16) := '1';		-- $AC000..$AFFFF UMA
				when "01100" => COMPARE_BITMASK(15) := '1';		-- $B0000..$B3FFF UMA
				when "01101" => COMPARE_BITMASK(14) := '1';		-- $B4000..$B7FFF UMA
				when "01110" => COMPARE_BITMASK(13) := '1';		-- $B8000..$BBFFF UMA
				when "01111" => COMPARE_BITMASK(12) := '1';		-- $BC000..$BFFFF UMA
				when "10000" => COMPARE_BITMASK(11) := '1';		-- $C0000..$C3FFF UMA
				when "10001" => COMPARE_BITMASK(10) := '1';		-- $C4000..$C7FFF UMA
				when "10010" => COMPARE_BITMASK(9)  := '1';		-- $C8000..$CBFFF UMA
				when "10011" => COMPARE_BITMASK(8)  := '1';		-- $CC000..$CFFFF UMA
				when "10100" => COMPARE_BITMASK(7)  := '1';		-- $D0000..$D3FFF UMA
				when "10101" => COMPARE_BITMASK(6)  := '1';		-- $D4000..$D7FFF UMA
				when "10110" => COMPARE_BITMASK(5)  := '1';		-- $D8000..$DBFFF UMA
				when "10111" => COMPARE_BITMASK(4)  := '1';		-- $DC000..$DFFFF UMA
				when "11000" => COMPARE_BITMASK(3)  := '1';		-- $E0000..$E3FFF UMA
				when "11001" => COMPARE_BITMASK(2)  := '1';		-- $E4000..$E7FFF UMA
				when "11010" => COMPARE_BITMASK(1)  := '1';		-- $E8000..$EBFFF UMA
				when "11011" => COMPARE_BITMASK(0)  := '1';		-- $EC000..$EFFFF UMA
				when others => null;
			end case;
			if (COMPARE_BITMASK and REGISTER_EMS) /= "00000000000000000000" then
				Result := MEMORY_EMS;
			elsif (COMPARE_BITMASK and REGISTER_UMB) /= "00000000000000000000" then
				Result := MEMORY_SRAM;
			end if;
		end if;
		return Result;
	end function;
end architecture;
mkarcher
LAN Manager
Beiträge: 204
Registriert: Fr 5. Jun 2020, 19:38

Re: EMS 3.2 unter DOS (<= 286)

Beitrag von mkarcher »

Für EMS: Du verlässt dich darauf, dass der Treiber 4 zusammenhängende Seiten in der REGISTER_EMS-Bitmaske eingetragen hat. Dann sind nämlich die Adressbits 14 und 15 ein eindeutiger identifikator, welche der vier Seiten das ist, in meinem Beispiel von oben:
  • C800:0-C800:3FFF -> A15 = 1, A14 = 0, also "Seite 2"
  • CC00:0-CC00:3FFF -> A15 = 1, A14 = 1, also "Seite 3"
  • D000:0-D000:3FFF -> A15 = 0, A15 = 0, also "Seite 0"
  • D400:0-D400:3FFF -> A15 = 0, A15 = 1, also "Seite 1"
Das ist jetzt gegenüber den physischen Seitennummern im Page-Frame um 2 verschoben, aber das solltest Du in Software (im EMS-Treiber) ausgleichen können, so dass Du bei der Feststellung "EMS angesprochen" aus der Adresse direkt ablesen kannst, welches Page-Register relevant ist.

Für UMBs hätte ich erwartet, dass Du gar kein Remapping machst, sondern einfach 512KB für 8000-FFFF hinterlegst, und die deaktivierten Bereiche nicht verwendet werden - ähnlich die das die Lo-Tech 1MB-Karte macht. Dann kannst Du A14-A18 direkt in die RAM-Adressierung übernehmen.
Jackintosh
MemMaker-Benutzer
Beiträge: 57
Registriert: Di 25. Okt 2022, 15:46

Re: EMS 3.2 unter DOS (<= 286)

Beitrag von Jackintosh »

Nachdem ich das Projekt abgespeckt habe, passt es immer noch nicht mal ansatzweise in das CPLD. Nachdem der Fitter nach über 4 Stunden immer noch zu keiner Lösung kam, habe ich abgebrochen. Projekt gestorben.
Antworten