[Coco] os9/drivewire driver: success!
Aaron Wolfe
aawolfe at gmail.com
Tue Nov 10 13:18:14 EST 2009
One question about combining SERREAD and SERCHECK:
My original idea was that SERCHECK would return the number of bytes in
the server's buffer, and then SERREAD would ask for a flush of X
bytes, typically the number returned by SERCHECK. The server would
then write out the # of bytes requested. This was (in my head) a way
to improve performance for things like rzsz over the virtual serial
port.
By combining them, I will be cutting the potential throughput in half
since there are two bytes for each data byte, and also taking a
penalty of having to ask for each byte individually (which is
admittedly how my current driver works, but it was supposed to be
better :)
Are there outside factors that mitigate the losses in combining the
calls? If there is some other reason it will be slow anyway, then I
agree it would make it simpler to combine them.
-Aaron
On Tue, Nov 10, 2009 at 7:05 AM, Boisy G. Pitre <boisy at tee-boy.com> wrote:
> Aaron,
>
> Again, fantastic work. It is great to see someone taking the bull by the horns, learning the tools and expanding on the existing work in the NitrOS-9 project.
>
> I downloaded the source to the scdwt driver and looked over it. I have a few suggestions that I think you may want to look at.
>
> Typically in an OS-9 SCF driver, the read routine uses the V.BUSY/V.WAKE SCF variables to handhshake with an interrupt service routine (ISR) to coordinate obtaining data from an input buffer that is filled by the ISR itself. There is no real interrupt in this particular case, but OS-9 provide something called a Virtual Interrupt (VIRQ) that you can use for situations just like this. Here's how it works:
>
> You can set up the VIRQ through the F$VIRQ system call to call an ISR that you provide for some interval. The period of the OS-9 tick is 1/60 second. You supply a multiplier to the F$VIRQ call to extend the period that the VIRQ calls your ISR, so you could have your ISR get called every 6 ticks, which means your ISR gets called 10 times per second. You can adjust this number as you wish for optimality.
>
> Your ISR, when called, would send a OP_SERREAD call to the server. I would combine the OP_SERCHECK and OP_SERREAD into one call. When you send the OP_SERREAD, the server would send back two bytes. The first byte would flag whether there is a valid byte to send, and the second byte would be that byte. So for example:
>
> ISR sends OP_SERREAD
> Server returns: 0x00 0x00 (first byte indicates that there is no data to send, second byte is just a fill byte)
> OR
> Server returns: 0xFF 0x41 (first byte indicates that there is data from the server, and the second byte is the valid character)
>
> In your ISR, you have to take into account that a response may not come in because the server isn't running, the cable is unplugged, etc, and take action accordingly, but assuming everything is ok, you get back a response immediately. IF the first byte is 0, you just return. However IF the first byte is non-zero, you take the second byte and stuff it away into a queue and increments a queue count static variable.
>
> Back to your Read routine. When SCF calls your Read routine, it copies the process ID of the process who is calling the Read routine into the V.BUSY static storage variable. When the Read routine is entered, it should check the queue count, and if zero (implying there is no data to read), it should copy V.BUSY to V.WAKE (effectively copying the process ID of the process that is doing the Read), then do an indefinite F$Sleep.
>
> Meanwhile, back to the ISR... when it finally does get a valid byte from the server, it will put away the data byte into the input queue, increment the queue count as I stated earlier, and then check V.WAKE. if V.WAKE is 0 (meaning no process is sleeping, waiting for data), it merely returns. If, however, V.WAKE is no-zero, then the ISR will send an S$WAKE signal to the process ID in V.WAKE. In the case where there is a process asleep, it will wake up and continue running in your Read routine.
>
> Back to you read routine, the code immediately after the os9 F$Sleep wakes up reads the byte from the input queue. Note there are some additional checks to be done for Level 2, such as whether the process is in a suspend state, and whether the signal is an S$Intrpt or lower signal in which case it doesn't read the character but immediately returns with an error.
>
> My suggestion would be to look in sc6551.asm and its Read routine for an idea of the flow of control from the ISR back to the read routine. But the idea is to use the VIRQ (which is driven by the system clock module) to make your driver much more hospitable to the OS-9 environment.
>
> Feel free to post questions up here as you go through this.
>
>> Ok, PTY is working and it's much nicer than the old stdin/stdout
>> version. I am now using an OS9 shell in Minicom on my linux box, with
>> the Coco booted and accessing disks over the same serial cable at the
>> same time.. the bit banger must be hating life :)
>>
>> I made a web page with notes and files if anyone wants to play with
>> it, or better yet help find/correct my many mistakes and bad designs.
>> I think it should have everything needed:
>>
>> http://www.aaronwolfe.com/coco/
>>
>> It's very close to usable, but if you're just interested in having it
>> work then probably want to wait another week or so and I'll have it
>> much better polished.
>>
>> -Aaron
>>
>>
>>
>>> John
>>> --
>>> John W. Linville Someday the world will need a hero, and you
>>> linville at tuxdriver.com might be all we have. Be ready.
>>>
>>> --
>>> Coco mailing list
>>> Coco at maltedmedia.com
>>> http://five.pairlist.net/mailman/listinfo/coco
>>>
>>
>> --
>> Coco mailing list
>> Coco at maltedmedia.com
>> http://five.pairlist.net/mailman/listinfo/coco
>
>
> --
> Coco mailing list
> Coco at maltedmedia.com
> http://five.pairlist.net/mailman/listinfo/coco
>
More information about the Coco
mailing list