From: Spiro Trikaliotis (ml-cbmhackers_at_trikaliotis.net)
Date: 2004-06-12 12:09:31
Hello Jim, * On Thu, Jun 10, 2004 at 01:22:00AM -0500 Jim Brain wrote: > For reading of files using GET# and such, I found the CBM would simply > drop ATN when it had enough data to fulfill the request. Hu? The ATN is dropped immediately after an OPEN, CLOSE, LISTEN/TALK or UNLISTEN/UNTALK (with perhaps the secondary address) is sent. If you want to send something, you have to wait for the listener to signal "ready" (see, for example, wait_for_listener() in CBM4LINUX, or $ED5A-$ED5E in the C64 ROM disassembly, or $E94B-$E957 in the Floppy 1541, ROM -03 and -05). The TALKer sets CLOCK to LOW to signal it wants to send, and the LISTENer can hold this until it sets DATA to HIGH. The programmer's reference guide has a good diagram of this in chapter 6, "the serial bus". Look for T_H ("Listener hold off"). So, there is no need to send bytes more than once. > As of right now, I seem to be having one issue that shows up when > sending the command channel results back to the interface. FOr some > reason, my code wants an extra byte to be sent after the EOI character > (the last char to be sent). Due to the way I wrote the interface code, > sending an extra 0 doesn;t hurt, but I need to figure out what the issue > is at some point. As the EOI is sent *before* the last byte (the TALKer does not set the clock after at most 200 us after the LISTENer signalled "I'm ready" by setting DATA to HIGH, as above, with CLOCK going low (T_NE, "Non-EOI repsponde to RFD"), but waits for the LISTENer to recognized this and signalling it with putting DATA again to LOW after T_YE, "EOI Response time", for T_EI, "EOI Response Hold Time", you have to send a byte after the EOI. Have a look how the C64 kernal handles this: The "real" output to the bus is at $ED40. Anyway, $EDDD (which is called from the kernal jump table, $FFA8) wraps around it so that is delays the output by 1 data byte: $EDDD BIT $94 $EDDF BMI $EDE6 $EDE1 SEC $EDE2 ROR $94 $EDE4 BNE $EDEB $EDE6 PHA $EDE7 JSR $ED40 $EDEA PLA $EDEB STA $95 $EDED CLC $EDEE RTS $94 is negative whenever there is already a byte buffered. So, at start, it is positive, so $EDE1/$EDE2 set it to negative. $EDE4 is non-conditional, as Z=0 is always true here, so $EDEB stores the byte to $95 and returns without any error. The next time $EDDD is called, $94 is negative, this $EDDF jumps to $EDE6, which remembers the current byte to be output on the stack, outputs THE BUFFERED byte ($ED40 does not look at the Accu, but at $95), gets the new byte and stores it to $95. This way, there is no need to output an extra byte. > Does a DOS command get executed upon receipt of EOI char, or when > UNLISTEN is sent? I have not checked too deeply (in fact, the 1541 side really is a mess, compared with the C64 part), but it seems to me that it is executed immediately after the EOI is recognized: The routine started at $E85B which handles the IEC bus goes to $E8E7 when a LISTEN has been encountered (via E8A9-E8B5, E8D2, E8E3, E8E7). Then JSR $EA2E gets the data bytes from the IEC bus into the command buffer. For this, it jump to $CFB7 (at EA48) which iteself is the only routine that sets $0255, the flag for the main loop that there is a command. $0255 is incremented, whenever there is an EOI signalled ($CFE8-CFF0) with a zero value in $F8. $0255 is used in the main loop (EBF0-EBF7) to find out if there is any command. If yes, EBFC handles it by calling C146. (CFEE, EBF1, EBF8 are the only locations where 55 02 is there in the 1541's ROM -03). I do not see the necessity for an UNLISTEN before, but I'm willing to be corrected. I tried with VICE and true drive emulation: I set breakpoints to UNLISTEN ($E88B), the command execution call at $EBF5, and the store to $0255 at $CFED. My ideas seems to be supported, although I always received the UNLISTEN before the command was executed. That is because $EA2E-$EA56 calls $E9C9 to get a data byte from the bus, which itself tests for ATN. Thus, the UNLISTEN is processed before the main loop is called again. I disable the sending of UNLISTEN on the C64 side by putting RTS at $EDFE. $CFED was not called after this, unless a CLOSE 1 was executed. (I excuted open 1,8,15,"v0" for these tests, as well as CLOSE1.) Thus, something in my logic is wrong: Without the UNLISTEN, the 1541 does not recognize the command. I checked again: OPEN1,8,15,"V0": $CFED was not called. OPEN 2,8,15,"I0": Now, $CFED was called. It seems that the processing of the commands need a subsequent ATN, whatever it is (LISTEN, UNLISTEN, TALK, UNTALK). Good, point taken. > It looks like you can use channel 0 and 1 in regular open commands, but > 0 must be used for reading, and 1 must be used for writing. Can someone > confirm? Yes, channel 0 assumes ",P,R" at the end, while channel 1 assumes ",P,W". > If you get a LISTEN, then a TKSA, what should you do? Signal an error, do nothing. IMHO, this is a clear violation of the protocol, so you have to assume that something went wrong. Do not do anything with the bus unless you are "opened" (LISTEN, TALK, OPEN, CLOSE) again. > If you get a LISTEN, then a SECOND, then a TALK/TKSA, what do you do? Whenever you get a LISTEN or TALK, it "overrides" the previous state. Have a look at the 1541's kernal at $E89B-$E8A7: Whenever a TALK has been recognized ($E89B-E89D), the TALK state is set ($E89F-E8A1) and the LISTEN state is reset (E8A5-E8A7). For LISTEN, it is quite the opposite ($E8A9-E8B5). > And, to save space, there's a theme going here. Do you use the last > commands received, or do you error out? I don't understand this question. HTH, Spiro. -- Spiro R. Trikaliotis http://www.trikaliotis.net/ Message was sent through the cbm-hackers mailing list
Archive generated by hypermail pre-2.1.8.