CDROM reading issue after subcpu halt

Ask anything your want about Mega/SegaCD programming.

Moderator: Mask of Destiny

Fonzie
Genny lover
Posts: 323
Joined: Tue Aug 29, 2006 11:17 am
Contact:

CDROM reading issue after subcpu halt

Post by Fonzie » Tue Feb 06, 2007 2:40 pm

Héhé :P I canned FMV for now and tried to fix tavern rpg engine...

The major point is that the maincpu engine halt the subcpu to read/write to its ram (i cannot use the flip flop word ram, since its 100% full).
Okay, it appear to work pretty good on real hardware exept one thing:

When I halt/unhalt even once the subcpu, any attempt to read data off the disc hang (the red led stays on after halt).
Of course, sub cpu still run and can execute any type of "non-loading" commands :)

:arrow: I tried to add a delay before each "halt", i also tried to disactivate Vint before "halting" but nothing really happen, still hang. So i suspected it could be cause of the crazy segacd bios... I added debug code everywhere (10KB of debug code out of 58KB) for almost all things... And figured out that subcpu hang at this point (when trying to read data again):
mcd_wait_cdc_stat();

And the code is :

/*
###################################################################
Wait CDC_STAT ARRIVE TO 1 O_o
CDC stat^^
entry : _CDBIOS
IN: d0.w : Function Number (cdcstat)
Out:cscc
Break : do/d1/a0/a1
Func :
CDCSTAT 00008AH Check if prepared data here or not
*/

.align 4
.globl mcd_wait_cdc_stat
mcd_wait_cdc_stat:
Check:
move.w #0x8A, %d0
jsr 0x5f22
bcs Check
rts

:arrow: I assume that halting subcpu break something , so the wait_cdc_stat function loop forever or even hang inside the segacd bios...
I cross finguer that it simply loop forever...

Also, for segacd specialists, what should i do after detecting the error? I already tried to CDROM_stop and read again without success...

Thx a lot

Fonzie

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Tue Feb 06, 2007 8:45 pm

A couple thoughts:

Does your function keep looping or does it never return from the BIOS? Either way, the BIOS could be getting corrupted. Maybe you could try masking all interrupts on the subcpu before the halt.

Are you stopping the CD before the halt and restarting afterwards? If you're not stopping, it could be as easy as calling for a ROMPAUSE beforehand.

Fonzie
Genny lover
Posts: 323
Joined: Tue Aug 29, 2006 11:17 am
Contact:

Post by Fonzie » Tue Feb 06, 2007 11:10 pm

Thx Tasco :)

I added PauseON and PauseOFF functions and it hang 50% of the time, again it ends in the wait_cdc_stat function... Even if i try to read again, it do very random result.

The first 3 loadings are ok... the 4th one got hang / corrupt 75% of time and the 5th one (after an halt/unhalt) hang 100% time.

hang = keeps looping in the wait_cdc_stat

It keeps looping in wait_cdc_stat... I tried to add a delay + init all stuff if delay over... Work very randomely and loop forever for the 5th loading everytime.

There is something extremely wrong somewhere in my process... absolutely... Maybe i call too many bios functions too fast... But there is no delay given in the documentation.


Well, i start to think (i was already thinking) that this f****g hardware isn't for me...

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Tue Feb 06, 2007 11:27 pm

You should call CDBSTAT until it says it's paused. I don't know how long a delay that is but you'll just have to try it. You may be able to get away with calling CDBCHK until it succeeds but that won't guarantee that the CD is paused.

Fonzie
Genny lover
Posts: 323
Joined: Tue Aug 29, 2006 11:17 am
Contact:

Post by Fonzie » Wed Feb 07, 2007 1:24 pm

Thx a lot Tasco .
I cleaned all my code, used CDBSTAT after every bios call to check that bios isn't busy anymore and bios achieved the function i want to :P

I now always pause_ON after each load and start a new READ (since pause_off seems to hang/loop at wait_cdb_stat).
It work perfect on Gens, but i got better result in real hardware :)

Now each loading (before subcpu halt) is 100% secure/reliable. With incredible speed :) However, it hang after I halt/unhalt the subcpu, here (in one of those two loops, situated at the begining of the loading function).

mcd_comreg_write(0xA1,0x14);
mcd_cd_rom_read(sectorfrom);
while((mcd_get_cdb_stat()&0x8000)==0x8000){}//Wait no more busy
while((mcd_get_cdb_stat()&0xFF)!=1){}//Wait reading again :P

So, the halt thing seems to hang something in the bios (even if the bios paused the read and said "i'm no more doing anything".
Any new idea? Should i add CDBCHK too? :D

I'm quite happy all appear fine with pause_on :P Still hang after a halt but quite happy ;P

Mask of Destiny
Very interested
Posts: 616
Joined: Thu Nov 30, 2006 6:30 am

Post by Mask of Destiny » Wed Feb 07, 2007 6:27 pm

Is there some way to temporarily disable interrupt generation from the CDC? If I had to take a wild guess, I'd say that the CDC has problems if it doesn't get a proper IRQ acknowledgement and I would imagine that the 68K doesn't generate an IRQ ack signal when it's halted. Since the CDC (or whatever logic handles interrupts generated by the CDC anyway) never got an ack for the original IRQ it's possible it won't generate any more. I seem to remember that most of the CD BIOS functions wait for data from the interrupt handlers. If the interrupts never fire, they'll hang forever.

I'm not sure if this is actually the case though. I've never done any low level interaction with the CD hardware so I'm not really in a position to test my hypothesis.

Fonzie
Genny lover
Posts: 323
Joined: Tue Aug 29, 2006 11:17 am
Contact:

Post by Fonzie » Wed Feb 07, 2007 6:48 pm

Yeah, there is an interupt masker :)
And yeah, i confirm that the CDC generate interupts every few ms...

Nice you think a interupt disknowledge could hang CDC :) Sounds good to me...

Mask of Destiny
Very interested
Posts: 616
Joined: Thu Nov 30, 2006 6:30 am

Post by Mask of Destiny » Fri Feb 09, 2007 3:44 am

Fonzie wrote:Yeah, there is an interupt masker :)
Perhaps messing with this will get you your results. There's certainly plenty of room for it to not work even if the problem is interupt related, but it's worth a shot.
And yeah, i confirm that the CDC generate interupts every few ms...
Yeah, every 1/75th of a second when you're reading data off the drive. Not sure what other interupts it generates though.
Nice you think a interupt disknowledge could hang CDC :) Sounds good to me...
It's possible at least.

ob1
Very interested
Posts: 463
Joined: Wed Dec 06, 2006 9:01 am
Location: Aix-en-Provence, France

Post by ob1 » Fri Feb 09, 2007 5:49 am

Mask of Destiny wrote:Yeah, every 1/75th of a second when you're reading data off the drive.
Aren't these interrupts frame interrupts ? Not frame as a frame per image, but frame as in the CD-audio specification ? A CD-audio is 73'59"and 74 frames. Each second is divided in 74 frame.
Could it be ?

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Fri Feb 09, 2007 7:24 am

ob1 wrote:
Mask of Destiny wrote:Yeah, every 1/75th of a second when you're reading data off the drive.
Aren't these interrupts frame interrupts ? Not frame as a frame per image, but frame as in the CD-audio specification ? A CD-audio is 73'59"and 74 frames. Each second is divided in 74 frame.
Could it be ?
You mean 75 frames, and yes it is. It's a CDC decoder interrupt (CDC interrupt in the tech manual). Even if it keeps generating interrupts when the drive is paused, these interrupts can be disabled directly on the CDC.

One of the other interrupts comes from the CDD and is the source of communication between the drive and bios. I'd guess the CDD is freaking out because it's left waiting for the subcpu. You can turn off this communication but I don't know if you can turn it back on... safely. I hope it doesn't come to that.

The other interrupt is the subcode interrupt but we shouldn't have to worry about that.

Fonzie
Genny lover
Posts: 323
Joined: Tue Aug 29, 2006 11:17 am
Contact:

Post by Fonzie » Fri Feb 09, 2007 8:34 am

Thx guys.

I'll try to use the interrupt mask this evening :)
Btw, steve told me that a "kick start" to the cdc may be required after letting him without interupts for a while, this confirm what you say :)

Fonzie
Genny lover
Posts: 323
Joined: Tue Aug 29, 2006 11:17 am
Contact:

Post by Fonzie » Sat Feb 10, 2007 1:22 pm

Ok, working now ... Yeppee :D
The trick :

-Mask all interupts before halting (writting 0xFFFF to the mask register, need to be verified because the documentation seems to sux).
-After unhalt, kick start the CDD.

It works on model2 hardware... however, it is unsure that it is perfect because kega shows a "open tray" icon everytime I kick start the cdd.
Thank a lot guys :D And my master, steve :)

Now need to fix other bugs (my maincpu code related) ;)

Mask of Destiny
Very interested
Posts: 616
Joined: Thu Nov 30, 2006 6:30 am

Post by Mask of Destiny » Sat Feb 10, 2007 1:58 pm

So what do you have to do to "kick" the CDD?

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Sat Feb 10, 2007 6:56 pm

Fonzie wrote:-Mask all interupts before halting (writting 0xFFFF to the mask register, need to be verified because the documentation seems to sux).
Save the (byte) value at $FF8033, write 0x7E to $FF8033, and, after the unhalt, restore the original value to $FF8033.
Fonzie wrote:-After unhalt, kick start the CDD.
I'd really like to see the code. :wink:

Fonzie
Genny lover
Posts: 323
Joined: Tue Aug 29, 2006 11:17 am
Contact:

Post by Fonzie » Sat Feb 10, 2007 11:12 pm

Yeah, i'm writting 0xFFFF instead of 0x7E , but it is same result :P
Thank you for the confirmation.

After not receiving reply from the bios, the CDD stops to work... Thanks to the method of steve, i fixed the problem (partialy since it shows a "open tray" on KEGA, seems wierd).
Here is my code for Halt/Unhalt preparation process :P Subcpu side of course.

Code: Select all

if(command==0x0401)//Halting perparation requested
  {
      interruptmask=scpu_interruptmask[0];
      scpu_interruptmask[0]=0xFFFF;
  }
else if(command==0x0402)//UnHalting perparation requested
  {
      scpu_interruptmask[0]=interruptmask;

      pc=(unsigned char*)0xFF8037;
      *pc=0x0;
      for(i=0;i<32;i++){asm("nop");}
      *pc=0x4; //Kick start CDD!
}
Enjoy!
After kick start, the CDD appear to work again, no more hang :) héhé, magic :D

Post Reply