General Category > LisaList2

Good grief, why is it so hard to eject a disk?

(1/3) > >>

stepleton:
Suppose you had to tell someone writing bare-metal code to make a Lisa 2 eject a floppy disk. (The code isn't in a multitasking setting --- it has full supervisor control over the processor and can just poll.) What would you tell them to do?

So far, my best guess is:

1. Disable interrupts on the 68000
2. Set parallel port VIA port B pin 6 (DSKDIAG -- is the controller busy?) to input
3. Set keyboard VIA port B pin 4 (FDIR -- floppy drive interrupt) to input

4. Poll DSKDIAG until the controller reports idle (it's probably idle to start with)

5. Issue command $85 $FF to the the controller to clear any interrupts
6. Poll DSKDIAG until the controller reports idle
7. Poll FDIR until it shows that any interrupt has been cleared

8. Issue command $81 $02 to the controller to eject the disk
9. Poll DSKDIAG until the controller reports idle
10. Poll FDIR until it shows an interrupt has been raised (i.e. the disk is out)

11. Issue command $85 $FF to the the controller to clear any interrupts
12. Poll DSKDIAG until the controller reports idle
13. Poll FDIR until it shows that any interrupt has been cleared

14. Restore interrupts on the 68000

Well, I'm not managing to get the Lisa to eject the disk. Instead, it seems to hang at step 10. Interestingly, if I put an ILLEGAL instruction between steps 8 and 9, the disk does eject (but of course my program crashes). Can anyone spot something I'm missing? Or does this look all right and instead the answer must just be a bug in my code?

rayarachelian:
Did this not work? (Shameless stolen from the Boot ROM source and ofc it's subroutines):

I expect that ILLEGAL will trigger an ISR which will then reset something back to some known state when the vector is taken to the Boot ROM.


--- Code: ---    1E56|                       ;-------------------------------------------------------------------------
    1E56|                       ;  Subroutine to eject disk
    1E56|                       ;  Assumes A0 = ptr to disk shared memory
    1E56|                       ;-------------------------------------------------------------------------
    1E56|
    1E56|                       EJCTDSK
    1E56|                               .IF     NEWTWIG = 1
    1E56| 611A                          BSR.S   CLRFDIR          ;ensure interrupts cleared
    1E58| 6516                          BCS.S   @1               ;exit if error
    1E5A| 243C 0018 0000                MOVE.L  #EJCTTIME,D2     ;set eject timeout
    1E60|                               .ENDC
    1E60| 117C 0002 0002                MOVE.B  #UNCLAMP,CMD(A0) ;set up cmd
    1E66| 10BC 0081                     MOVE.B  #EXRW,(A0)       ;go do it
    1E6A| 61D2                          BSR.S   CHKFIN           ;wait for FDIR
    1E6C| 6502                          BCS.S   @1               ;skip if error
    1E6E| 6102                          BSR.S   CLRFDIR          ;clear intrpt and return
    1E70| 4E75                  @1      RTS
    1E72|

--- End code ---

It's looking like the ROM code does the eject command backwards, first it writes the 02 at the higher address, and then the 81 at the CMD/GoByte address. If you're writing 81 02 in normal order by writing a long to just the odd bytes (i.e. MOVE.L #$ff02ff81,(a0) where the ff's are even addresses that are thrown away ) it's possible that the 6504 will see 81 first without the 02 and act on it? - just a wild guess.

The 68000 being big endian and the 6504 being little might make a difference here too in terms of the order they see things on the bus?

Also at step 9 you're checking for DISKDIAG, but the ROM is checking for FDIR and ignores DISKDIAG immediately after issuing the command, so this suggests that explains your infinite loop - the ILLEGAL is just a clue here.


--- Code: ---1E3E|                       ;----------------------------------------------------------------------------
1E3E|                       ;  Subroutine to check for disk interrupt (FDIR asserted) - loop takes 8.8us
1E3E|                       ;  Destroys register D3 and A3
1E3E|                       ;----------------------------------------------------------------------------
1E3E|
1E3E|                       CHKFIN
1E3E|                               .IF  NEWTWIG = 0
1E3E|                               .ENDC
1E3E|                               .IF  NEWTWIG = 1
1E3E| 2602                          MOVE.L  D2,D3           ;set user-supplied timeout
1E40|                               .ENDC
1E40| 267C 00FC DD81                MOVE.L  #VIA1BASE,A3    ;set ptr for interface
1E46| 0813 0004             @1      BTST    #4,(A3)         ;FDIR?
1E4A| 6608                          BNE.S   @2              ;exit if yes
1E4C| 5383                          SUBQ.L  #1,D3
1E4E| 66F6                          BNE.S   @1              ;else loop
1E50| 003C 0001                     ORI.B   #$01,CCR        ;set error
1E54| 4E75                  @2      RTS

--- End code ---

stepleton:
Thanks Ray. Sadly, I thought of the byte order and command-issue concerns and just didn't mention them here :)
Like the boot ROM does, I copy the command data into the Floppy IOB (memory area) byte-by-byte, first the parameter byte and then the "gobyte". (Backwards.) So it can't be a case of early triggering: since the gobyte is the last byte in, the floppy controller should have all it needs to interpret the command successfully.

I'll look into the "ignoring DSKDIAG" thing. It's confusing if this is the problem, though --- why would the 68000 polling the 6522 affect the controller ejecting the disk once it's received a command?

rayarachelian:

--- Quote from: stepleton on March 24, 2021, 06:21:51 am ---I'll look into the "ignoring DSKDIAG" thing. It's confusing if this is the problem, though --- why would the 68000 polling the 6522 affect the controller ejecting the disk once it's received a command?

--- End quote ---

Can't say for sure other than to say if you're looping on DISKDIAG, and its value doesn't change, then 68000 might hang. It shouldn't affect what the 6504 does.
Another thing you could do is check the status in floppy RAM instead to see if it took the command byte and then report on it, though I'd put some NOPs in there to allow the 6504 to be able to access the shared RAM.

Either looking at the schematic or the 6504 code itself might give a hint as to what's happening when looping on DSKDIAG.

There are weird things in the Lisa, for example, the MMU latches can be enabled by READING their addresses, not just writing. You wouldn't expect that, but if you look at the schematic, you'd see and go, oh yes, that's why, as much as it is unexpected.

I'm not saying that's what you're seeing here, but rather, I'm saying don't assume anything is going to have no effect elsewhere.

We do have a working example in the Boot ROM source code, so moving your code closer to that code's behavior will likely help narrow things down, and once you get your code working, you can experiment and figure out what things interfere with it after.

stepleton:
Finally worked it out. What an almighty pain that was. I'm not sure I've even got it all yet, but I've managed to sidestep several of the booby traps. For all the hardship, at least I made my code easier to troubleshoot in the meantime.

The various Lisa Hardware Manuals you can find online do not quite prepare you for how picky the floppy drive system can be. Here are the main things that got me:

1. The documentation for the DRIVE ENABLE command (page 195 in the 1983 manual) says that the byte at $FCC003 needs to be a mask saying which drive you want to enable, and that bits 0-2,4-6 of that byte are "don't care". LIES. Those bits will be 0 or your code won't work.

2. At the bottom of just about all of those command description pages in the manual, you'll see "Pre issue requirements" for a command that usually include "DSKDIAG high" and "gobyte zeroed". You'd better pay attention to both! My fault for assuming that DSKDIAG high (which might be interpreted as the drive controller saying "I'm not busy!") would imply "gobyte zeroed". Turns out that it doesn't, and strange things happen if you plow ahead without checking the gobyte.

3. Don't issue the disk eject command and then just quit to the ROM: the Lisa will crash. You need to wait for and clear the interrupt that the ejection procedure will raise, since (I guess) the ROM won't be ready to handle it.

Combinations of getting these things wrong can either crash the machine or lead to nothing happening at all. Either way, unless you get it right, the disk will just sit there in the drive. Since your debugging interventions (e.g. putting in ILLEGAL instructions to verify that execution has reached a certain point, or just plain-old bugs in your temporary code) can also crash the machine, it's hard to tell what's going on.

I hope there aren't many more surprises now!

Navigation

[0] Message Index

[#] Next page

Go to full version