Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?
Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?
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?
@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
) 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:
Test Code:
So I wrote a test cartridge program to read MOTOR_COUNT(0000:0440) (or so I think, 8088 amateur here
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
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
Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?
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.
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!
Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?
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:
Mike
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?
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:
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
I ran the simplified code example:
Code: Select all
MAIN:
sti
INF:
jmp INF
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
Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?
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?
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:
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:
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
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
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 ;----------------------------------------------------------------
Re: Cartridge Boot Sequence (IPL-able), int 13h required to stop diskette spinning?
I'm a moron. The interrupts are getting disabled because your ROM code is being executed by the INT 18h hook. An interrupt call:
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.
- 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
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?
That...
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
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