Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Discussions on programming older machines
Trixter
Posts: 720
Joined: Mon Sep 01, 2008 12:00 am
Location: Illinois, USA
Contact:

Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Post by Trixter »

Looking forward to your experiments :-)
You're all insane and trying to steal my magic bag!
ImperatorBanana
Posts: 20
Joined: Sat Mar 06, 2021 9:12 am

Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Post by ImperatorBanana »

@Brutman + anyone mildly curious about it,

So I wrote a test cartridge program to read MOTOR_COUNT(0000:0440) (or so I think, 8088 amateur here :lol: ) and save it to RAM at the very beginning, and it looks like by the time the BIOS gives my MAIN control via the int 18h call, the MOTOR_COUNT is already 0 or ends up at 0 within a handful of cycles of me getting control. We'll see how my schedule is this week for getting some time to check 046C the other timer ticks.

Notes:
int_dos: I wanted a svc_dos_printstr function (ah=09h) but since my cartridge is running on raw BIOS I just wrote crude equivalent, then through in a few other additions (svc_dos_printwd prints out a hex word, svc_dos_printnl does a newline). I didn't want to bog down the post with the entire source code for the utility functions but I'm more than willing to post it.
SAVERAND: I wanted to prove as part of the test I was actually reading data where I thought it was, so I picked two memory locations, stored the motorcount in one, a random value (EFh) in the other, and then made sure when my screen printed I got what I expected for the random value, thus being slightly more confident that the motor count value I got was correct. I didn't make my utility functions specifically print a byte so the leading 00's are expected as I set DH to 0 as part of setting ES.

Output:

Code: Select all

SAVECOUNT: 0000
SAVERAND: 00EF
Test Code:

Code: Select all

MAIN1: ; Called by BIOS int 18h 
	MOTORCOUNT dw 0440h	
	SAVERAND dw 2000h ;; Random RAM address
	SAVECOUNT dw 2002h ;; Random RAM address
	;; Save Motor count
	mov dx,0000h
	mov es,dx
	mov al,byte ptr es:MOTORCOUNT
	mov byte ptr es:SAVECOUNT,al
	; Save some random data to make sure writing and reading is actually working
	mov ax,0BEEFh
	mov byte ptr es:SAVERAND,al ; intentionally only writing a byte
		
	call SETUP_TEST ; Sets up the video mode and int_dos for printing

	;; Printout text and saved off count variable
	mov ah,svc_dos_printstr
	mov dx,OFFSET savecounttext
	int int_dos
	mov dx,0000h
	mov es,dx
	mov dl,byte ptr es:SAVECOUNT
	mov ah,svc_dos_printwd
	int int_dos
	mov ah,svc_dos_printnl
	int int_dos
	
	;; Printout text and saved off random data
	mov ah,svc_dos_printstr
	mov dx,OFFSET saverandtext
	int int_dos
	mov dx,0000h
	mov es,dx	
	mov dl,byte ptr es:SAVERAND
	mov ah,svc_dos_printwd
	int int_dos
	mov ah,svc_dos_printnl
	int int_dos

INF:
	jmp INF ; infinite loop
Trixter
Posts: 720
Joined: Mon Sep 01, 2008 12:00 am
Location: Illinois, USA
Contact:

Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Post by Trixter »

0:046c = 40:6c
The latter form is what you'll see more often; here's why: 400h = 1024 = the end of the interrupt table = where the BIOS Data Area is stored. Since the BDA is listed in the tech ref BIOS source code as offsets from 0, it's customary to refer to it as 0040:0000 so that you can match the offsets in the BIOS source with the system. 6C is the timer tick DWORD, so you look at 0040:006C. That sort of thing.

I have a sneaking suspicion if you put STI at the beginning of your source, the motor will shut off after 3 seconds, but I could be wrong.
You're all insane and trying to steal my magic bag!
Brutman
Site Admin
Posts: 1331
Joined: Sat Jun 21, 2008 5:03 pm
Contact:

Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Post by Brutman »

Funny, but I was going to write the same thing last night and I just didn't get through the draft ...

You are making this too complicated. Let's simplify:
  • Put an STI to renable interrupts at the beginning of your code. If it works then you know that interrupts were disabled and never turned back on.
  • Checking for the motor count counting down or the timer ticks counting up just confirms that interrupts are happening as they should. If the time ticks is not moving, then you definitely are not going to have the floppy drive motor turn on.

Mike
ImperatorBanana
Posts: 20
Joined: Sat Mar 06, 2021 9:12 am

Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Post by ImperatorBanana »

Sorry for the complications, I'm usually in the 3D printing mindset when I code where I'm juggling a bunch of experiments simultaneously to optimize my limited time but in this case I should've focused.

I ran the simplified code example:

Code: Select all

MAIN:
     sti
INF:
     jmp INF
and as you both correctly predicted, the diskette drive stops spinning. So far the known options are:

0.) Never give back control during BIOS ROM check (Mouser Cart method), bypasses the whole problem but never initializes the diskette drive
1.) sti (Brutman/Trixter method [possibly also BASIC Cart])
2.) int 10h/ah 00h (ImperatorBanana method)
3.) Whatever CrossFire/Mineshaft is doing (so far by replacing various CrossFire function calls with infinite loops, I think I narrowed it down to e000:0154 e8 2d 02 (Call <function> @ e000:0384)). Whatever that function or one of its sub functions is doing ends up halting the diskette drive spin.

I was curious about the STI instruction and stumbled upon Wikipedia talking about the interrupt flags and saying that POPF can do it (which makes sense), so it's possible Sierra was modifying a value on the stack and popping it back into the flags register with the interrupt flag set. At least as far as the thread title is concerned: Nope, int10h is not required but I'm pretty sure somewhere there's a dusty IBM document in someone's attic saying an IPL cartridge shall do one of the above things to pass QA :lol:
Trixter
Posts: 720
Joined: Mon Sep 01, 2008 12:00 am
Location: Illinois, USA
Contact:

Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Post by Trixter »

What I'm curious about: Does IBM's documentation, as previously referenced, mention that interrupts are disabled when passing control to ROMs?
You're all insane and trying to steal my magic bag!
ImperatorBanana
Posts: 20
Joined: Sat Mar 06, 2021 9:12 am

Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Post by ImperatorBanana »

I haven't been able to find anything in the English text sections. I've read through various sections on the cartridges, diskette sections, BIOS programming, etc. with no luck on something disabling interrupts without re-enabling them (the disk IO stuff does seem to disable them but in theory it re-enables them unless there's an oddball bug.

The bootstrap is A-26. Ironically the first thing the bootstrap does is STI, then sets the video mode 00h (it's neat to learn what's triggering the display change to the blank screen with the blinking cursor right before the drive starts spinning), then it checks the diskette for boot sectors, and int 18h's which is the handoff to the cartridge when no disk is present.

There are definitely a bunch of comments talking about needing multiple retries in the disk routines to actually detect failure, and some interesting comments on the interrupt line being flakey, but until I get better at 8088 if it's in there I'm definitely not seeing it.

A-26:

Code: Select all

F000:0B1B ; ---	int 0x19 -------------------------------
F000:0B1B ; boot strap loader
F000:0B1B ;
F000:0B1B ; track 0, sector 1 is read into the
F000:0B1B ; boot location (segment 0, offset 7c00)
F000:0B1B ; and	control	is transferred there
F000:0B1B ;
F000:0B1B ; if the diskette is not present or has a
F000:0B1B ; problem loading  (e.g., not	ready),	and int.
F000:0B1B ; 18h	is executed. if	a cartridge has	vectored
F000:0B1B ; int	18h to itself, control will be passed to
F000:0B1B ; the	cartridge.
F000:0B1B ; --------------------------------------------
F000:0B1B boot_strap	  proc near		  ; CODE XREF: F000:E6F2j
F000:0B1B					  ; DATA XREF: F000:FF15o
F000:0B1B		  sti			  ; enable interrupts
F000:0B1C		  sub	  ax, ax	  ; set	40x25 b&w mode on crt
F000:0B1E		  int	  10h
F000:0B20		  sub	  ax, ax	  ; establish addressing
F000:0B22		  mov	  ds, ax
F000:0B24 ;----- see if	diskette is present
F000:0B24		  in	  al, 62h	  ; get	config bits
F000:0B26		  and	  al, 100b	  ; is diskette	present?
F000:0B28		  jnz	  short	h3	  ; no,	then attempt to	go to cart
F000:0B2A ;----- reset the disk	parameter table	vector
F000:0B2A		  mov	  word ptr ds:78h, offset disk_parms ; (int 0x1e offset)
F000:0B30		  mov	  word ptr ds:7Ah, cs ;	(int 0x1e segment)
F000:0B34 ;----- load system from diskette -- cx has retry count
F000:0B34		  mov	  cx, 4		  ; set	retry count
F000:0B37 h1:					  ; CODE XREF: boot_strap+35j
F000:0B37		  push	  cx		  ; save retry count
F000:0B38		  mov	  ah, 0		  ; reset the diskette system
F000:0B3A		  int	  13h		  ; diskette_io
F000:0B3C		  jb	  short	h2	  ; if error, try again
F000:0B3E		  mov	  ax, 201h	  ; read in the	single sector
F000:0B41		  sub	  dx, dx	  ; to the boot	location
F000:0B43		  mov	  es, dx
F000:0B45		  mov	  bx, 7C00h	  ; (boot location)
F000:0B48		  mov	  cx, 1		  ; drive 0, head 0, sector 1, track 0
F000:0B4B		  int	  13h		  ; diskette_io
F000:0B4D h2:					  ; CODE XREF: boot_strap+21j
F000:0B4D		  pop	  cx		  ; recover retry count
F000:0B4E		  jnb	  short	h3a	  ; cf set by unsuccessful read
F000:0B50		  loop	  h1		  ; do it for retry times
F000:0B52 ;----- unable	to ips from diskette
F000:0B52 h3:					  ; CODE XREF: boot_strap+Dj
F000:0B52		  int	  18h		  ; go to basic	or cartridge
F000:0B54 ;----- ips was successful
F000:0B54 h3a:					  ; CODE XREF: boot_strap+33j
F000:0B54		  jmp	  far ptr 0:7C00h ; (boot location)
F000:0B54 boot_strap	  endp
A-74:
INT 13h description:
Note: If an error is reported by the diskette code, the appropriate action is to reset the diskette, then retry the opteration. On read accesses, no motor start delay is taken, so that three retries are required on reads to ensure that the problem is not due to motor startup.

A-77:

Code: Select all

F000:EDFB ;----------------------------------------------------------------
F000:EDFB ;***note***
F000:EDFB ;	   given the current system configuration a method is needed
F000:EDFB ;	   to pull the nec out of "fatal error"	situations. a timer
F000:EDFB ;	   on the adapter card is provided which will perform this
F000:EDFB ;	   function. the watchdog timer	on the adapter card is enabled
F000:EDFB ;	   and strobed before the 8259 interrupt 6 line	is enabled.
F000:EDFB ;	   this	is because of a	glitch on the line large enough	to
F000:EDFB ;	   trigger and interrupt.
F000:EDFB ;----------------------------------------------------------------
I suppose it would be somewhat interesting at some point to dump various PCJr ROM BIOS's to see if they behave differently but that's a backburner thing for me. If you ever come across any PCJr-specific actual programmers guides (not just the "How to do all the BASICs") let me know! I know LGR on youtube actually had some success tweeting at Ken Williams about the Super JR he got at
Trixter
Posts: 720
Joined: Mon Sep 01, 2008 12:00 am
Location: Illinois, USA
Contact:

Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Post by Trixter »

I'm a moron. The interrupts are getting disabled because your ROM code is being executed by the INT 18h hook. An interrupt call:
  • Pushes the flags
  • Clears the trap and interrupt flags
  • Pushes CS
  • Pushes IP
  • Loads CS:IP with the value found in the interrupt vector table
So there you go. Interrupts are disabled upon entry to anything called via software interrupt. (IRET pops flags, thereby restoring interrupts, but you'll never get there so you need to put STI in your code.)

On another note: Where did you get that BIOS source/disassembly? I only have the scanned tech ref. It would be great to get it in ASCII. I thought it was one of the reconstructions over at https://sites.google.com/site/pcdosretro/ibmpcbios but I don't see one for the PCjr there.
You're all insane and trying to steal my magic bag!
ImperatorBanana
Posts: 20
Joined: Sat Mar 06, 2021 9:12 am

Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?

Post by ImperatorBanana »

That... :lol: oh goodness makes perfect sense, THANK YOU! I've played a decent amount with hardware interrupts on embedded platforms but really never dealt with SW interrupts as an API (which I think is a pretty neat design choice) so for some reason my brain refused to process the idea that an interrupt is an interrupt and you have to think about what happens to the interrupt flag on that platform once you're in one.

PCJr BIOS
Someone posted the disassembly using IDA Pro of PC, PCJr, and a few Tandy' 1000s at https://github.com/ricardoquesada/bios-8088 . They didn't enter all the comments (hence the page A-74 reference behind hand typed by me), but it's been nice to be able to do some snooping without having to flip around in the tech ref for it. One of my many experiments is trying to figure out how to modularly Ghidra disassemble so I can do the BIOS and Cartridges. Note that they seem to have replicated some of the spacing from the tech ref, so searching for "int 18h" comes up with nothing but "int 18h" (I assume there's a tab in there) does. The tooling nowadays is pretty amazing. Last night I was also looking at the tech ref for the Jr's sibling the IBM JX to see if maybe they included more detail in the Cartridge introduction about IPL cartridges and look at the boot strap routine. The internet archive's OCR was somewhat decent and reasonably searchable (though the scan is a bit rough): https://archive.org/details/jx-technica ... e/mode/2up
Post Reply