Kernal I/O problem

Started by FMan, August 02, 2007, 07:47 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

FMan

I was writing a little bit of code in the monitor to write a sector to disk. Problem is, it doesn't work. The code worked fine, before I added another disk command (B-P) as I remembered and tested that this is necessary prior to U2.

I am asking for a programmer to see my code and tell me why it causes I/O Error #5. I have been looking at it for days and it's driven me crazy. I've been unable to fix it!

The code loads to $1300 and executes from same address, to write sector 18/0 from $B00. Be warned! It writes over the root block (when it works). There is no problem, when I remove the subroutine call at $1303.

This subroutine was added to send the B-P command. Without it, the writing works fine. With it, there is a DEVICE NOT PRESENT error when sending the U2 command late in the routine.

I cannot fathom why that error is even remotely possible. It is noted, that opening and closing the command channel twice in a row is lame, but this was just test code and now I simply must know what the problem is for the sake of knowing what the problem is!

Please help. Kernal I/O is hell... Oh, start the program with GF1300. I will really appreciate it, if someone can tell me why the code fails in this really weird way. Thanks!

Mark Smith

------------------------------------------------------------------------------------------------------------------

Commodore 128, 512K 1750 REU, 1581, 1571, 1541-II, MMC64 + MP3@64, Retro-Replay + RR-Net and a 1541 Ultimate with 16MB REU, IDE64 v4.1 + 4GB CF :-)

wte

Ok, what are you doing?
1300 jsr 1380 --> open 8,8,8,"#"
1303 jsr 1340 --> open 4,8,15,"B-P:8 0"
1306/1308 --> close#4
130B/130D--> chkout#8
... --> Data output
131b jsr 1393 --> open 4,8,15, "U2 8 0 18 0"
131e/1320 --> close#8
1323/1325 --> close#4
1308 --> clrch
... --> print "OK" back to monitor

You have to close first (!) #4 and at last #8.
Change the code in the lines
131e/1320 --> close#8
1323/1325 --> close#4

to
131e/1320 --> close#4
1323/1325 --> close#8

That's all!

regards WTE

Edit1: Sorry I dont't know if this really works. I just tried it on VICE. First (original code) I got the I/O Error #2. After changing the sequence of the file close commands the programm works correctly. But now - again testing the original code - I doesn't get any error - ups? :förvånad: It think it has to be tested on a real C128.

Edit2: Got my mistake! I had to use "true drive emulation" in VICE. Now I get the Error #5 - everytime :(

Edit3: OK, more testing. I checked the status flag during the data transfer. The status is $00, $03, $83, $83 ... [Error #5]
Oh, holy sh.. :förbannad:
1306/1308 --> close#4
is closing of a file with channel (secondary address) 15!!!
It is not a problem of the c128, it is a "problem" of the disk drive. Every time than you close channel 15, the floppy is closing all files! So your data is running against a wall, because closing #4 is closing file #8 too (on the floppy side).
If you want to close #4 on the C128 side without loosing all connections (for file #8) you have to set the carry flag (SEC) before jumping to the close routine ($ffc3) this will close #4 on the C128 and prevent to close channel 15 on the disk drive. [And that is also the reason why the problem is not perceivable in VICE without "true drive emulation on"]

LDA #$04
SEC
JSR $FF3C

should solve your problem. [Always have a look on the little flags :D]

hydrophilic

I agree with wte, the problem is the closing of file 4 = channel 15.  This problem and similar ones are best avoided by following a rule found in Commodore's disk drive manuals:

open the command channel first (e.g., open 4,8,15)
close the command channel last (e.g., close 4)

With this method you would have to change the code at 1393 from an open4... to a print#4... and remove the close4 at 1306.  In other words,

open 4,8,15 -> lda #4; ldx #8; ldy #f; jsr ffba; lda #0; jsr ffbd; jsr ffc0
open 8,8,8,"#" (you got that)
print#4,"B-P 8 0" -> ldx #4; jsr ffc9; ldy #0; setptr: lda string,y; jsr ffd2; iny; cpy #length; bne setptr; jsr ffcc
data out (you got that)
print#4,"U2 8 0 18 0" -> same as first print#4 but different string/length
close 8 (you got that)
close 4 (you got that)

I've never tried it, but you may be able to use the kernal PRIMM routine to make the print#x code shorter (no loop).

Good luck!

wte

Today in the very early morning I needed more than an hour to locate the real error. It was short-time after midnight in Europe... May be, that was the reason for the first (wrong) shot. Quick and dirty is mostly only dirty ;-(

You can do like hydrophilic said (open channel 15 first and once). That is the way you have to do on a C64 (if you use kernal routines).

The C128 has the CLC/SEC option in the kernal. Closing a file with channel 15 and Carry Set  will not close the channel on disk.
This is because the disk commands of BASIC 7.0 use channel 15 and the user should also be able to work with the command cannel.

The SEC-trick works perfectly. I tested it 2 hours after midnight ;-)

Regards, WTE
----------------
www.c128.net

FMan

Yup, like I said, the problem wasn't as easy as it first appears and I had already tried all the "easy fixes", that I could think of, before coming here. :) For some reason I was still unable to get it to work with the SEC trick so I did what I usually do when having problems: I gave up. :P

I just initially wanted to have the code compressed to as small as I could and do a bit of a dirty hack to accomplish what I wanted to do, but this probably wasn't a good idea, so I will re-do the whole thing properly this time and hope to get better results... Thanks very much for the help!