[comp.sys.amiga] serial port expansion

jesup@pawl17.pawl.rpi.edu (Randell E. Jesup) (01/06/88)

[This is a piece of mail I recieved from Bryce re serial port expansion.     ]
[I am posting this response to both usenet and bix, as the issues raised here]
[are important to all developers and users.  His text is '>', mine is the    ]
[rest.  Note - Bryce's text is all here.  REJ				     ]

> Just a quick note to let you know what is going on:
> 
> I am *at this moment* implementing a multiple serial port controller.  The 
> first hardware is due out 1Q 88, I believe.  The software should pre-date 
> this.
> 
> More docs will be made available soon.  Once it is out *every* hardware
> manufacturer will have equal access to the materials.  Things are still
> a bit rubbery, in case changes need to be made.

	I like this idea in theory.  However, I still disagree with your
implemetation, and other serial manufacturers may also.

> I should have direct BIX access in 2-3 weeks.

	Good.  All you need is a MC/Visa and a phone call (see byte).

> The serial.device changing priority is *not* a problem.  My driver can link
> ahead of it no matter what it's priority, just by insterting at the head
> of the list.  Besides, Commodore is not planning on changing the serial
> device for V1.3 or V1.4 (they don't have anyone to do it; this comes from
> both bart and jimm).

	The real problem is not the priority, but how it is mounted:  How can
you have two serial.devices in the devs: directory?  You can't, of course.
You can link in drivers before the regular serial.device by running a
program, but this is NOT the same as OpenDevice("serial.device",...).
	Remember the Amiga device scheme is set up for LOADABLE, dynamic
devices.  They aren't loaded until needed, which is part of their beauty.

	So, now, one more time I'll make my point:  The one and only thing
needed to handle any number of serial ports is a name-mapping utility.  If
a scheme is based on assigning unit numbers according to when they register
with your high-priority serial.device during binddrivers, there are several
problems:
	1. The unit numbers will depend on the order in which they register.
	   This means it will not neccesarily be the same from one boot
	   to the next, and the user will have no means but experimentation
	   to figure out which unit is attached to what.
	2. Your device must be loaded and have created it's port before
	   binddrivers is executed, it opens the old serial.device, AND
	   each driver that registers MUST (of course) be in memory to
	   register.  Therefor, all the serial drivers end up in memory
	   always (longer boots (PLEASE NO!), less memory, more disk
	   grinding).

My contention is that all one needs is a name-mapper, that maps what thing
(modem, laserwriter, whatever) you want to open to a device and unit number.
If you read my last posting there is a long explanation of this.

> Thanks for echoing BIX <---> USENET.  Both sides of that fence should have
> a say in this.

	Certainly.  However, for things that mainly involve developers and
Commodore itself, I feel you should have said something on bix OR usenet
before you did.  Your first message (that I replied to on usenet, pointing you
at the ongoing conversation on bix) implied 'that since no one else is doing
anything about it, I decided that I should, and here it is.'

> You comments are appreciated!  The only comment of yours that has me
> baffled is the one about not wanting the drivers to be loaded ahead of time.
> Just how would you propose NOT having at least something loaded?  Remember
> that my design goal is multiple serial ports from multiple manufactueres
> all on one machine.  Maximum user installation must be "clicking or dragging"
> an icon.

	It's easy to come up with a design that doesn't require any of the
serial drivers to be loaded until they are opened.  All you need is a name-
mapper that knows about the entries you've dragged over.  Of course, you can
customize them as well (for example, the microbotics serial card might
default to MB_Serial_1 and MB_Serial_2.  If you installed a modem on the second
port, you could either keep calling it MB_Serial_2, or you could double-click
on the 'Serial Names' icon that came with this new wonderful multi-serial port
handling software, and tell it MB_Serial_2 is also a Modem, and a Modem_2400.
	One of the advantages of this scheme (using name-mapping INSTEAD of
higher unit numbers) is that installing another board won't affect anything
you have already set up.
	As I have said, it requires no more work for those writing programs
than adding higher unit number support does.  (See my last message)

	You said yourself you planned to have a name-mapper, that maps names
to unit numbers.  If you have that, why not something that maps names to
device/unit number pairs?  I think no user should EVER have to care about
unit numbers, just about what piece of hardware they attached to which board.
Terminal programs would default to opening 'modem', which of course the user
could change.  This way, when the user got a new program that uses a modem,
he wouldn't have to tell it he always uses unit 3 as the modem, but just runs
it (assuming he bothered telling the system at some point that that piece
of hardware was connected to a modem, otherwise he tells it MB_Serial_1 or
whatever.)  Once he's told it once that there's a modem there, he doen't have
to worry about configuring every piece of software.  (Or worry about changing
the configurations when he adds a new board or causes the order in which
binddrivers reads the files in the expansion drawer to change.)

	I'm sorry if I go on at length, but I feel strongly about this, as I
suspect whatever we come up with will be around a long time.  And once again,
even if I seem derisive, I'm just trying to make some points.  I thought I
had explained them sufficiently in my last message, so I'm being a bit more
explicit in my criticisms.

	Bryce:  Call microbotics ASAP.  They are also doing a serial port
(and other things) board right now, and you should talk to them.  Talk to
Redmond Simonsen, who has been following this on Bix.

----------------------------------------------------------------------------
Randell Jesup, Lunge Software.				(518) 272-2942
Bix: rjesup
usenet: beowulf!lunge!jesup@steinmetz.UUCP
     //	Randell Jesup			Lunge Software Development
    //	Dedicated Amiga Programmer	13 Frear Ave, Troy, NY 12180
 \\//	lunge!jesup@beowulf.UUCP	(518) 272-2942
  \/    (uunet!steinmetz!beowulf!lunge!jesup)

ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) (01/07/88)

[ Aren't you hungry for ASCII text now? ]

	Bryce and Randall seem to be beating each other over the head with
foam bats regarding extending the serial.device to support multiple devices
and make it transparent to the programmer.  If I might make a suggestion....

	If I were going to do this, I would try to make it as transparent as
possible, with a minimum of skullduggery.  Programmers (and indeed, existing
programs) should not be able to tell the difference, and should run
identically (if they were written correctly).

	Unit 0 should remain the internal serial port.  Units 1 - MAXINT
should represent external ports.  Exactly which ports they'd be would be
vendor-specific.  The hardware expansion would come with a disk with an
installation program.  The installation program would do the following:

	Find the existing serial.device file in the DEVS: directory.  Rename
the file to something else (intser.device?), and patch the file itself to
reflect this change.  Next, copy into DEVS: the new serial.device, which
knows about the external ports.

	This new serial.device also knows about the "old", renamed serial
driver.  When a program opens the serial.device, the vendor's handler checks
the unit number.  If it's zero, it opens the old one.  The device would then
check subsequent I/O transactions to see if they are intended for unit zero.
If so, it just re-posts the transaction to the original driver, who will
process it and return it to the calling program.

	I project that this would slow down internal device transactions
minimally, and is sufficiently transparent that it wouldn't cause anything
untoward to happen.  The only icky thing I can think of is that IOF_QUICK
transactions might get mucked up.

	I think this is a better approach as it avoids going behind Exec's
back (it doesn't mess around with Exec's (probably private, don't-mess-with-
these) lists).  Comments?

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
Leo L. Schwab -- The Guy in The Cape	ihnp4!ptsfa -\
 \_ -_		Recumbent Bikes:	      dual ---> !{well,unicom}!ewhac
O----^o	      The Only Way To Fly.	      hplabs / (pronounced "AE-wack")
"Work FOR?  I don't work FOR anybody!  I'm just having fun."  -- The Doctor

louie@trantor.umd.edu (Louis A. Mamakos) (01/08/88)

In article <4918@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes:
>	Unit 0 should remain the internal serial port.  Units 1 - MAXINT
>should represent external ports.

Yes! Yes!  Don't make the system more complicated at this level, please!

>	This new serial.device also knows about the "old", renamed serial
>driver.  When a program opens the serial.device, the vendor's handler checks
>the unit number.  If it's zero, it opens the old one.  The device would then
>check subsequent I/O transactions to see if they are intended for unit zero.
>If so, it just re-posts the transaction to the original driver, who will
>process it and return it to the calling program.

I don't really agree that the vendor's serial device driver should be doing
this;  I think a seperate program should.  What if I have more than one
vendor's serial board in my system?  That at least 3 serial device drivers.

It should be quite easy to hack up a simple serial.device that can redirect
to any number of alternative serial device drivers.  If anyone wants to
donate a multiport serial interface for an A2000, I'd be glad to write
write such a beast ;-) (1/2)  Please, one that can do DMA!


>	I project that this would slow down internal device transactions
>minimally, and is sufficiently transparent that it wouldn't cause anything
>untoward to happen.  The only icky thing I can think of is that IOF_QUICK
>transactions might get mucked up.

In fact, this solution doesn't slow things down at all.  When you pass the
I/O Request packet off to the REAL (old) serial.device, it will fill in the
io_Device and io_Unit (I think they're called this, off hand) to point to
itself.  Subsequent DoIO()/SendIO()/BeginIO() requests will be done directly
to the device described by io_Device in the I/O request.

The neat thing 'bout this solution is that the drivers for units 1-n don't
have to be resident in memory until/unless they are used.  You can be clever
in this 'clearinghouse' serial.device, and have it read a configuration 
file that maps serial.device unit numbers into (device,unit) tuples.

I believe that this symbolic naming should be done at a higher level where
I can ignore it, and not have to pay the extra overhead to fool with it.

Louis A. Mamakos  WA3YMH    Internet: louie@TRANTOR.UMD.EDU
University of Maryland, Computer Science Center - Systems Programming

cmcmanis%pepper@Sun.COM (Chuck McManis) (01/08/88)

In article <4918@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes:
>[ Aren't you hungry for ASCII text now? ]
>	Unit 0 should remain the internal serial port.  Units 1 - MAXINT
>should represent external ports.  Exactly which ports they'd be would be
>vendor-specific.  The hardware expansion would come with a disk with an
>installation program.  The installation program would do the following:
>
>	Find the existing serial.device file in the DEVS: directory.  Rename
>the file to something else (intser.device?), and patch the file itself to
>reflect this change.  Next, copy into DEVS: the new serial.device, which
>knows about the external ports.

This works fine for the first device, the next device you 'install' 
blows away the new serial.device, yuck. I think that serial.device should
be left alone and not bothered. Then you define a new thing in the world
that can be identified on the devs list as a serial device. DLT_SERIAL
maybe. Personally, I think that this device should have a handler associated
with it that should be associated with serial kinda things, much like disks
have handlers associated with them which do disk kinda things. The default
handler would be something AUX:/CON: like and probably ROM resident. This
thing would be announced as a new "feature" of 1.x and DOCUMENTED so that
any program could enumerate all of the serial devices just like they 
enumerate all of the disk devices. Add a series of commands you can send
to them like the CON: handler but with other info in them like baudrate
and RS232 flags, give the handler a buffer that can be read byte at a 
time and works JUST like the CON:/AUX: handlers. No one loses compatibility
because serial.device is still serial.device, manufacturers of software are
happy because a) if they don't rev their products it still works, and b)
there is an opportunity to rev the product and 'add value' which gives them
an opportunity to get some more revenue from updates. And lastly none
of the hardware manufacturers have to talk to the software writers, voila
end of problem. Hell, if we name them COMn: it will save all those PC 
converts some grief.

>	This new serial.device also knows about the "old", renamed serial
>driver.  When a program opens the serial.device, the vendor's handler checks
>the unit number.  If it's zero, it opens the old one.  The device would then
>check subsequent I/O transactions to see if they are intended for unit zero.
>If so, it just re-posts the transaction to the original driver, who will
>process it and return it to the calling program.

Open caches some stuff in the IORequest like the task pointer of the 
driver code. Once you've opened there wouldn't be any delays because 
all further calls would go right to the serial.device task.

>	I project that this would slow down internal device transactions
>minimally, and is sufficiently transparent that it wouldn't cause anything
>untoward to happen.  The only icky thing I can think of is that IOF_QUICK
>transactions might get mucked up.
>
>	I think this is a better approach as it avoids going behind Exec's
>back (it doesn't mess around with Exec's (probably private, don't-mess-with-
>these) lists).  Comments?

Its a good suggestion Leo for the first add on serial port but doesn't 
have that infinite expandibility that we have grown so used to with the
other stuff in the system. Other Comments?


--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.

bryce@hoser.berkeley.edu (Bryce Nesbitt) (01/08/88)

In article <4918@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes:
>	I project that this would slow down internal device transactions
>minimally...

Or not at all.  Recall that OpenDevice() fills in the io_Device field with
the device pointer.  After the open, calls would go directly to the 
proper device.  The only (tiny) assumption here is that a programmer
must not assume that all units of a device have the same io_Device.


>	I think this is a better approach as it avoids going behind Exec's
>back (it doesn't mess around with Exec's (probably private, don't-mess-with-
>these) lists).  Comments?

Leo is talking about the suggestion bart** made and I picked up that fools
the system in a controlled way.  Basically the first "serial.device" would
be linked AHEAD of the next in the device list.  When "OpenDevice"
chains down looking for the "serial.device" it finds yours first.
The old, dumb device is LAST in the chain.

	Let's keep this discussion going.  I'm not yet fully satisfied
	with any of the proposals as of yet.  Getting close, however.


** bart is the "Manager of Amiga ROM Software".  Messing with this should
not be a problem.  It was presented to me as either "approved" or
"approvable" by Commodore.


Please people!  Before you make the next comment on this, check out
the AutoConfig spec.  Also read the file called "drivers.doc".  You should
find it in the file "ReadMe1.2:Autodocs/autodocs.arc".  This is one
of the disks from the V1.2 Native Developer update kit.


>Leo L. Schwab

|\ /|  . Ack! (NAK, SOH, EOT)
{o O} . bryce@hoser.berkeley.EDU -or- ucbvax!hoser!bryce (or try "cogsci")
 (")
  U	"Your theory is crazy... but not crazy enought to be true." -Niels Bohr

bryce@hoser.berkeley.edu (Bryce Nesbitt) (01/08/88)

In article <38256@sun.uucp> cmcmanis@sun.UUCP (Chuck McManis) writes:
>In article <4918@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes:
>>
>>	Find the existing serial.device file in the DEVS: directory...
>
>This works fine for the first device, the next device you 'install' 
>blows away the new serial.device, yuck.

You didn't read Leo's posting close enough.  Each driver as it goes
in patches itself with the name of the one it renamed.  So you would
have a chain:

	serial.device	;New serial 2
	old2.serial	;New serial 1
	old1.serial	;The serial.device we know and love

See my response to his posting, AND READ the "drivers.doc" file from your
Autodocs "README" disk. 

Thanks for the idea Leo, I want to hear them all!  I don't happen to
like the suggestion much, but the input is welcome.  


>Other Comments?

Please!  Let's echo this stuff from here to BIX and back.  Throw
ALL the ideas out.  Let's get a GOOD standard.  As I said, I have
a "new_serial.device" that will go to a multiple port board that
is under development.
I'll still change my code to reflect whatever gets hashed out.

The problems I see are:

1> Does not match the "clean" autoconfig spec, as mentioned in "drivers.doc"
2> Problems with how NOT to load all of the drivers in, yet still know
   how many there are and what the names might be.

The non-problems are:

1> leaving the old serial.device in place.  This is easy.

|\ /|  . Ack! (NAK, SOH, EOT)
{o O} . bryce@hoser.berkeley.EDU -or- ucbvax!hoser!bryce (or try "cogsci")
 (")
  U	"Your theory is crazy... but not crazy enought to be true." -Niels Bohr

andy@cbmvax.UUCP (Andy Finkel) (01/09/88)

In article <22440@ucbvax.BERKELEY.EDU> bryce@hoser.berkeley.edu (Bryce Nesbitt) writes:
>In article <4918@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes:
>>	I project that this would slow down internal device transactions
>>minimally...
>
>Or not at all.  Recall that OpenDevice() fills in the io_Device field with
>the device pointer.  After the open, calls would go directly to the 
>proper device.

What about the CloseDevice() ?
Seems like you'll need some additional magic then.

			andy
-- 
andy finkel		{ihnp4|seismo|allegra}!cbmvax!andy 
Commodore-Amiga, Inc.

"Any sufficiently advanced technology is indistinguishable from
 a rigged demo."

Any expressed opinions are mine; but feel free to share.
I disclaim all responsibilities, all shapes, all sizes, all colors.

jesup@pawl21.pawl.rpi.edu (Randell E. Jesup) (01/09/88)

In article <4918@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes:
>	Bryce and Randall seem to be beating each other over the head with
>foam bats regarding extending the serial.device to support multiple devices
>and make it transparent to the programmer.  If I might make a suggestion....

Hmm, I thought I was using hardwood... :-) :-)  Actually, I'm more interested
in making it transparent to the user than to the programmer, though it would
be nice for that to be fairly transparent as well.

>	If I were going to do this, I would try to make it as transparent as
>possible, with a minimum of skullduggery.  Programmers (and indeed, existing
>programs) should not be able to tell the difference, and should run
>identically (if they were written correctly).

For old programs, yes.  The current mechanism that programs use (opening
serial.device unit 0) is insufficient for the future.  Part of this extension,
both Bryce and I agree (I believe) is ways to make old programs that think
they are opening the internal port actually open another port.  

>	Unit 0 should remain the internal serial port.  Units 1 - MAXINT
>should represent external ports.  Exactly which ports they'd be would be
>vendor-specific.  The hardware expansion would come with a disk with an
>installation program.  The installation program would do the following:
>
>	Find the existing serial.device file in the DEVS: directory.  Rename
>the file to something else (intser.device?), and patch the file itself to
>reflect this change.  Next, copy into DEVS: the new serial.device, which
>knows about the external ports.

Sorry, this is a kludge, and will not work if someone installs boards with
serial ports from multiple manufacturers.
I propose that for new programs that use the serial port, the following
be used:
		First, try to open a serial port with the device you
	want (Modem, Laserwriter, whatever) via the mapper.device  The
	IORequest passed in the OpenDevice, is shown in a previous message,
	It has a pointer to an initialized IOExtSer structure, flags, and
	the name of the thing you want to open.  If the OpenDevice fails
	because the person doesn't have it (and probably has no extra
	serial ports) then it should do an OpenDevice using the IOExtSer
	of serial.device, unit 0.  It would look like this:

		<set up IOExtSer as always>
		IOExtMap.Serial = &IOExtSer;
		IOExtMap.Flags  = MAPFLAGS;
		IOExtMap.Name   = "Modem";
		if (OpenDevice("mapper.device",0,&IOExtMap,0))
			if (IOExtMap.Error)
				/*mapper exists but can't open desired device*/
				report some error
			else
				if (OpenDevice("serial.device,0,&IOExtSer,0))
					report error
		/* If we get here without error, we can use IOExtSer */

	Not all that much different than now.  Remember, I am assuming
	a seperate way of rerouting requests for serial.device unit 0 from
	old programs.  (Fairly easy to do)
	Among the many reasons I prefer a name mapper to using higher unit
	numbers is that to the user of a program, 'modem' is more meaningful
	than 'unit 4'.  Hopefully, a user of a program that used this wouldn't
	ever have to reconfigure his terminal program to tell it which unit
	the modem is on.  Once the system has been told, all programs can find
	it.

>	This new serial.device also knows about the "old", renamed serial
>driver.  When a program opens the serial.device, the vendor's handler checks
>the unit number.  If it's zero, it opens the old one.  The device would then
>check subsequent I/O transactions to see if they are intended for unit zero.
>If so, it just re-posts the transaction to the original driver, who will
>process it and return it to the calling program.
>
>	I project that this would slow down internal device transactions
>minimally, and is sufficiently transparent that it wouldn't cause anything
>untoward to happen.  The only icky thing I can think of is that IOF_QUICK
>transactions might get mucked up.

A lot of programs depend on the correct handling of IOF_QUICK.  Also,
IOF_QUICK can be MUCH faster, and allows programs to do 9600 baud vt100.

>	I think this is a better approach as it avoids going behind Exec's
>back (it doesn't mess around with Exec's (probably private, don't-mess-with-
>these) lists).  Comments?

Messing with exec lists is utterly EVIL.  My proposals stay within the 
documented usage of routines.

>_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
>Leo L. Schwab -- The Guy in The Cape	ihnp4!ptsfa -\
> \_ -_		Recumbent Bikes:	      dual ---> !{well,unicom}!ewhac
>O----^o	      The Only Way To Fly.	      hplabs / (pronounced "AE-wack")

P.S.  I am cross-posting this to BIX.

     //	Randell Jesup			Lunge Software Development
    //	Dedicated Amiga Programmer	13 Frear Ave, Troy, NY 12180
 \\//	lunge!jesup@beowulf.UUCP	(518) 272-2942
  \/    (uunet!steinmetz!beowulf!lunge!jesup)

bryce@hoser.berkeley.edu (Bryce Nesbitt) (01/09/88)

In article <3113@cbmvax.UUCP> andy@cbmvax.UUCP (Andy Finkel) writes:
>In article <> bryce@hoser.berkeley.edu (Bryce Nesbitt) writes:
>>
>>Or not at all.  Recall that OpenDevice() fills in the io_Device field with
>>the device pointer....
>
>What about the CloseDevice() ?
>Seems like you'll need some additional magic then.

I'll give that a hesitent "Don't think so".  I'm assuming CloseDevice()
looks at io_Device and fires off a Close to the proper device.  The device
would decrement the count and perhaphs become expungeable.

We already HAVE to have a way of finding the device on OpenDevice(),
so no problem there.


I bounced on an attempt at disassembling CloseDevice().  It has some funky
ram patch that looks to be either setting up a frame pointer or a Global
Vector.  Ick!

|\ /|  . Ack! (NAK, SOH, EOT)
{o O} . bryce@hoser.berkeley.EDU -or- ucbvax!hoser!bryce (or try "cogsci")
 (")
  U	"Your theory is crazy... but not crazy enought to be true." -Niels Bohr

louie@trantor.umd.edu (Louis A. Mamakos) (01/11/88)

In article <22472@ucbvax.BERKELEY.EDU> bryce@hoser.berkeley.edu (Bryce Nesbitt) writes:

>I'll give that a hesitent "Don't think so".  I'm assuming CloseDevice()
>looks at io_Device and fires off a Close to the proper device.  The device
>would decrement the count and perhaphs become expungeable.

It appears that CloseDevice() dives through the io_Device field in the I/O
reqeust, so I don't think you have to do anything weird with CloseDevice, 
assuming you keep the OpenCount adjusted properly when you do the open and
"vector" off the the alternate device drivers.

>
>I bounced on an attempt at disassembling CloseDevice().  It has some funky
>ram patch that looks to be either setting up a frame pointer or a Global
>Vector.  Ick!

I'm not sure, but remember that when you do a CloseDevice(), the
Expunge entry point to the driver is called as well as the Close entry
point.  That might be what's going on.




Louis A. Mamakos  WA3YMH    Internet: louie@TRANTOR.UMD.EDU
University of Maryland, Computer Science Center - Systems Programming

daveh@cbmvax.UUCP (Dave Haynie) (01/12/88)

in article <4918@well.UUCP>, ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) says:

> 	Unit 0 should remain the internal serial port.  Units 1 - MAXINT
> should represent external ports.  Exactly which ports they'd be would be
> vendor-specific.  The hardware expansion would come with a disk with an
> installation program.  The installation program would do the following:

> 	Find the existing serial.device file in the DEVS: directory.  Rename
> the file to something else (intser.device?), and patch the file itself to
> reflect this change.  Next, copy into DEVS: the new serial.device, which
> knows about the external ports.

> 	This new serial.device also knows about the "old", renamed serial
> driver.  When a program opens the serial.device, the vendor's handler checks
> the unit number.  If it's zero, it opens the old one.  The device would then
> check subsequent I/O transactions to see if they are intended for unit zero.
> If so, it just re-posts the transaction to the original driver, who will
> process it and return it to the calling program.

This sounds OK, except for two possible problems.  The first one of these is
the case of multiple add-on serial cards (OK, so I'm getting extreme, but
someone has to).  If they're of the same vendor, there's a good chance that
they'd cooperate OK with his special "serial.device".  If they're of two
different vendors, there's a good chance that there will be a conflict,
since there's no good way for each driver to tell the other what unit number
it's up to.

The other problem involves how "L:Port-Handler" talks to the serial.device.
In the ideal case, I'd like to be able to add my additional serial devices
in my MountList.  Thus, I can deal with any number of vendor boards if I
need to, and I'm not going to have any special problems dealing with a 
serial device that's not called "serial.device".  And I can name my new
serial ports MODEM:, VAX:, and PC: if I so desire, and then I never have
to worry about what's connected to what.  And neither does the novice user.
A terminal program that supports multiple serial devices accepts the DOS
name of the device on the command line, or as a TOOLTYPE.  The program gets
the device and unit designation from the DOS name, so it has the device
abstraction afforded by DOS, plus the speed of directly acting on the 
EXEC level device and unit.

Only, that only really seems to work for filesystem devices.  The DOS device
list stores the SER:, PAR:, and PRT: devices, but has no obvious link to
an EXEC level device for such items.  It does reference the "L:Port-Handler",
but each of these devices is magically hardwired into the port handler.  That
makes add-on ports much more complicated, and much less general.

> 	I project that this would slow down internal device transactions
> minimally, and is sufficiently transparent that it wouldn't cause anything
> untoward to happen.  The only icky thing I can think of is that IOF_QUICK
> transactions might get mucked up.

Wouldn't this only slow up the initial opening of the device?  My special,
new serial.device sees a request for unit zero coming in.  So it supplies
the same information that the standard, unexpanded machine would for use
of the standard serial.device.  The device name is only meaningful to the
OpenDevice() call.

> Leo L. Schwab -- The Guy in The Cape	ihnp4!ptsfa -\
>  \_ -_		Recumbent Bikes:	      dual ---> !{well,unicom}!ewhac
> O----^o	      The Only Way To Fly.	      hplabs / (pronounced "AE-wack")
> "Work FOR?  I don't work FOR anybody!  I'm just having fun."  -- The Doctor

-- 
Dave Haynie  "The B2000 Guy"     Commodore-Amiga  "The Crew That Never Rests"
   {ihnp4|uunet|rutgers}!cbmvax!daveh      PLINK: D-DAVE H     BIX: hazy
		"I can't relax, 'cause I'm a Boinger!"

peter@nuchat.UUCP (Peter da Silva) (01/12/88)

Speaking of the Native developer's kit, I ordered mine back in November...

Back to the subject...

Please don't kludge in another serial.device or another nameserver without
first evaluating the possibility of using AmigaDOS as a name server... a
task it performs admirably and which is one of the few areas in which it's
an improvement on UNIX.

"SER2: the only way to grow."

jesup@pawl19.pawl.rpi.edu (Randell E. Jesup) (01/12/88)

In article <2179@umd5.umd.edu> louie@trantor.umd.edu (Louis A. Mamakos) writes:
>In article <4918@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes:
>>	Unit 0 should remain the internal serial port.  Units 1 - MAXINT
>>should represent external ports.
>
>Yes! Yes!  Don't make the system more complicated at this level, please!

	As I have said before, these higher unit numbers have no meaning
to the user, especially if you have multiple serial port expansions.
And my proposal for using a mapper is hardly at all more complicated than
the current method, and in fact is probably easier than having a requester
to ask the user what unit number to open (which the user might not know
either).  See the example code in a previous message to open a serial
device via the mapper.

>>	This new serial.device also knows about the "old", renamed serial
>>driver.  When a program opens the serial.device, the vendor's handler checks
>>the unit number.  If it's zero, it opens the old one.  The device would then
>>check subsequent I/O transactions to see if they are intended for unit zero.
>>If so, it just re-posts the transaction to the original driver, who will
>>process it and return it to the calling program.
>
>I don't really agree that the vendor's serial device driver should be doing
>this;  I think a seperate program should.  What if I have more than one
>vendor's serial board in my system?  That at least 3 serial device drivers.

	Exactly!  That's why I say we should use a mapper that opens the
appropriate serial device for you.

>The neat thing 'bout this solution is that the drivers for units 1-n don't
>have to be resident in memory until/unless they are used.  You can be clever
>in this 'clearinghouse' serial.device, and have it read a configuration 
>file that maps serial.device unit numbers into (device,unit) tuples.

	This is what my mapper is doing.  Using the mapper, you also don't
have to load any drivers until needed.  Also, you can do it without having
to have a 'mountlist-type' config file around, all the user needs to do
is to drag an icon over into his expansion drawer.

>I believe that this symbolic naming should be done at a higher level where
>I can ignore it, and not have to pay the extra overhead to fool with it.

	As I said, the overhead can be made almost nil, and I think a tiny
amount of overhead (only on open, plus 5-10 standard lines of code in
programs) is well worth it for an easier to use, more intuitive, and readily
expandable method of serial port expansion.

>Louis A. Mamakos  WA3YMH    Internet: louie@TRANTOR.UMD.EDU

     //	Randell Jesup			      Lunge Software Development
    //	Dedicated Amiga Programmer            13 Frear Ave, Troy, NY 12180
 \\//	beowulf!lunge!jesup@steinmetz.UUCP    (518) 272-2942
  \/    (uunet!steinmetz!beowulf!lunge!jesup) BIX: rjesup

jesup@pawl19.pawl.rpi.edu (Randell E. Jesup) (01/12/88)

In article <38256@sun.uucp> cmcmanis@sun.UUCP (Chuck McManis) writes:
...
>Personally, I think that this device should have a handler associated
>with it that should be associated with serial kinda things, much like disks
>have handlers associated with them which do disk kinda things. The default
>handler would be something AUX:/CON: like and probably ROM resident. This
>thing would be announced as a new "feature" of 1.x and DOCUMENTED so that
>any program could enumerate all of the serial devices just like they 
>enumerate all of the disk devices. Add a series of commands you can send
>to them like the CON: handler but with other info in them like baudrate
>and RS232 flags, give the handler a buffer that can be read byte at a 
>time and works JUST like the CON:/AUX: handlers.

	Very good idea; unfortunately, 99.9% of serial port dealing programs
use the device interface as opposed to the handler (ser:) interface.  1 (or
more) even uses the serial.resource, nothing we can do to help that one.

	One thing that should be part of any release of software to allow
more serial ports is a serx: handler.  With my plan, it would be opened
'SERX:name_of_thing/speed/flags/???' where name_of_thing is a name to
pass to the name mapper (mapper.device), for example 'serx:modem/1200/0'
which would open a serial port with a modem on it at 1200 baud.

>--Chuck McManis


     //	Randell Jesup			      Lunge Software Development
    //	Dedicated Amiga Programmer            13 Frear Ave, Troy, NY 12180
 \\//	beowulf!lunge!jesup@steinmetz.UUCP    (518) 272-2942
  \/    (uunet!steinmetz!beowulf!lunge!jesup) BIX: rjesup

dillon@CORY.BERKELEY.EDU (Matt Dillon) (01/12/88)

	The *real* problem is character loss.  If I disable task switching
I can read a 76.8Kbaud line with only one or two overruns every 30 seconds.
Needless to say, if I disable interrupts there would be no problems at all.

	IBM PC's don't have this problem 'cause nobody ever goes above
9600 baud, and do not usually use more than one port at a time anyway.
However, *I* like to go quite a bit faster...

	So *anybody* planning to do a multiple serial port expansion should
consider using a single chip microcomputer to buffer the data.  These are
not slow devices! and could easily handle, say, four 76.8KBaud lines each.

	In the DEC world this is known as SILOing.


				-Matt

jesup@pawl18.pawl.rpi.edu (Randell E. Jesup) (01/13/88)

In article <527@nuchat.UUCP> peter@nuchat.UUCP (Peter da Silva) writes:
>Please don't kludge in another serial.device or another nameserver without
>first evaluating the possibility of using AmigaDOS as a name server... a
>task it performs admirably and which is one of the few areas in which it's
>an improvement on UNIX.
>
>"SER2: the only way to grow."

	Better yet is to include a new serial handler that uses the
name server to decide which port to use.
	Example: XSER:modem, etc.  It should also be mountable with a permanent
connection as well, such as MODEM: (equivalent to above).

     //	Randell Jesup			      Lunge Software Development
    //	Dedicated Amiga Programmer            13 Frear Ave, Troy, NY 12180
 \\//	beowulf!lunge!jesup@steinmetz.UUCP    (518) 272-2942
  \/    (uunet!steinmetz!beowulf!lunge!jesup) BIX: rjesup

bryce@hoser.berkeley.edu (Bryce Nesbitt) (01/13/88)

Usually I agree with Mr. Jesup.  This time he forgot to do his research:


In article <204@imagine.PAWL.RPI.EDU> beowulf!lunge!jesup@steinmetz.UUCP writes:
>
>	As I have said before, these higher unit numbers have no meaning
>to the user, especially if you have multiple serial port expansions.

As I have said before.  Unit numbers have a lots of meaning.  How else
to I find the proper place to plug a cable?

>>The neat thing 'bout this solution is that the drivers for units 1-n don't
>>have to be resident in memory until/unless they are used.
>
>This is what my mapper is doing.  Using the mapper, you also don't
								     ^^^^^
>have to load any drivers until needed.  Also, you can do it without having
>to have a 'mountlist-type' config file around, all the user needs to do
>is to drag an icon over into his expansion drawer.
				  ^^^^^^^^^
Whoha!! As I pleaded last time, READ THE FILE "DRIVERS.DOC" from the
autodocs disk.  It is also in the A500/A2000 Technical reference guide.
I'd post it here, but I don't own the rights to it.

It is impossible to "drag an icon over into his expansion drawer" and
meet the goals you have set out in the past.  The stuff in the expansion
drawer WILL be loaded from the start.

Perhaphs we need a better Autoconfig spec... I don't really like the
requirement that Expansion drawer devices are always loaded.  I'd
prefer if the icon said "I'm truckduck.device units 1-9, load me
when needed".  But it is NOT what we have now.

The split between "added" devices in the Expansion drawer and "normal"
devices in DEVS: is also disturbing.


>>I believe that this symbolic naming should be done at a higher level where
>>I can ignore it, and not have to pay the extra overhead to fool with it.
>
>	As I said, the overhead can be made almost nil...

I don't like the idea of a separate "mapper.device" for several reasons.
One of them on the grounds of asthetics; ANOTHER different type of
device name abstraction?  If a mapperish thing is used, it ought to
be system wide, and user tranparent.

DOS name abstraction has some advantages, but what blows that for me
is the possibility of a user calling a disk "SER2".  Arbitrary,
unexplained tricks like that are NOT NICE to pull on the user.


	Is someone maintaining a coss-link to BIX on this topic?

|\ /|  . Ack! (NAK, SOH, EOT)
{o O} . bryce@hoser.berkeley.EDU -or- ucbvax!hoser!bryce (or try "cogsci")
 (")
  U	"Your theory is crazy... but not crazy enought to be true." -Niels Bohr

dillon@CORY.BERKELEY.EDU (Matt Dillon) (01/13/88)

	I have been following this discussion loosly.  It seems clear that
programs should have a way of setting the serial.device name and unit number. 
(or any other device they use...)

	And as far as having yet another device that determines which serial
device is actually used, this is quite easy to do without any modification
to the operating system.  Simply name the device serial.device and poof,
it gets all OpenDevice() calls.  It can then open the *real* serial.device
(with some other name... maybe serial0-5.device, etc...) and then die.

	The latter having the advantage that it is completely compatible, does
not require programmers to provide specifiable device names, does not require
serial.device's to know about each other, allows logical assignment of unit
ranges, and works with all existing programs.

----
DMA suggestion:	It shouldn't be too hard to have a little piece of
logic to handle DMAing to/from main memory from a single chip microcomputer. 
All it takes is a little latching logic for the address and data and a two or
three state machine to handle the bus transfer.  The rest would be handled
by a single chip microcomputer.  At the relatively slow rates serial goes
compared to the bus bandwidth, this would be a low-cost, highly efficient 
solution.

	Example: an MC68705, some 6551's, a couple of flipflops and some
	HC374's.  Using the MC68705 means the RAM, EPROM, and IO are in the
	processor.  You might want to use an HC6303 or 6805 instead, which
	have RAM+timer+lessIO onboard but not ROM.  Or you could even use one
	of those Intel single chip IO processors though I haven't looked at
	their specs.

				-Matt

ans@well.UUCP (Anne Schweizer) (01/14/88)

As I've heard, in the new release of vt100 2.8 you will be able to
specify a unit number. I think the idea of unit number is the best way
for programmers and even for the user. Useres are not *STUPID*. If they
have more than one disk drive, they know which one is Unit 0 and
which one is unit 1 and so on. I think it's the same on serial ports.

But there is another problem, older programs don't know anything about
unit numbers higher than 0. So my idea is, when some try to open
the serial.device unit 0 with OpenDevice() and this one is allocated by
program, so the new serial.device (which knows alls other serial devices
from a thing like a mountlist) should put up a requester which some
gadgets (one for each serial devices) and let the user choose the
unit.

-Anne.

mike@ronin.cc.umich.edu (Michael Nowak) (01/16/88)

In article <4990@well.UUCP> ans@well.UUCP (Anne Schweizer) writes:
>
>But there is another problem, older programs don't know anything about
>unit numbers higher than 0. So my idea is, when some try to open
>the serial.device unit 0 with OpenDevice() and this one is allocated by
>program, so the new serial.device (which knows alls other serial devices
>from a thing like a mountlist) should put up a requester which some
>gadgets (one for each serial devices) and let the user choose the
>unit.
>
>-Anne.

That's exactly what happens when you run MultiTalk, a program for the Mac
that allows several people to share several serial ports.  When any
application opens the serial device, you get a dialog box listing the
available ports on the network.  Similarly, in our case, the requester
would display a list of serial ports on the Amiga.


------------------------------------------------------------------------------
 In Real Life:	Michael Nowak                       "Seek truth from facts."
 Via Internet:	mike@ronin.cc.umich.edu                  - Deng Xiao Ping
 Via UUCP:	uunet!umix!ronin.cc.umich.edu!mike 

 Working for but in no way representing the University of Michigan.
------------------------------------------------------------------------------

jesup@pawl21.pawl.rpi.edu (Randell E. Jesup) (01/18/88)

/* This is a first cut at the in-memory data structures for the mapping and
   to identify what serial boards are in the system.  I've tried to make
   sure it is easily expanded in the future.  Comments and suggestions would
   be greatly appreciated, even more so from people doing serial expansion
   boards.  These are by no means graven in silly putty. :-)
   	Randell Jesup, Lunge Software, 13 Frear Ave, Troy, NY 12180
   	(518) 272-2942
*/

/* The structures were designed for easy use with the Exec list-handling */
/* routines.								 */
/* I've tried to make these multiples of 8 bytes long.			 */

struct Mapping {
	struct Node MappingNode;
	/* ln_Name points to null-terminated name, allocmem'ed */
	/* Flags should be null for now */
	/* Note: prioritized node - 0 is default */
	/* Type should be NT_UNKNOWN (0) */
	struct Mapping *NextMapping;	/* next mapping for same unit */
	struct SerialUnit *Unit;	/* which unit associated with */
	WORD MapReserved;		/* set to 0!!! */
};

struct SerialUnit {
	struct Node UnitNode;
	UWORD UnitNumber;
	ULONG Flags;			/* NULL for now */
	struct SerialUnit *NextUnit;	/* all units of a board are linked */
	struct SerialBoard *Board;	/* links back to board */
	struct Mapping *FirstMapping;	/* mappings for this unit */
	CPTR  UnitData;			/* for private use by driver */
	CPTR  UnitReserved;		/* Future expansion */
};

struct SerialBoard {
	struct Node SerialNode;	/* ln_Name should be set to device name */
			        /* Note: not with any path eg: myserial.device */
	UWORD NumUnits;		/* units on this board */
	ULONG Flags;		/* NULL for now */
	ULONG ManufacturerID;
	ULONG ProductID;
	CPTR  BoardAddress;	/* address board was assigned */
	CPTR  BoardData;	/* for driver private use */
	struct Device *Device;	/* null means not loaded */
	UBYTE *DeviceName;	/* file name of device to load */
				/* include path. eg: DEVS:myserial.device */
	struct SerialUnit *FirstUnit;
	/* The other units are linked through NextUnit to FirstUnit */
	CPTR  BoardReserved[2];	/* leave NULL!!!! */
};

struct MapperBase {
	struct Library MapLibrary;
	ULONG Flags;			/* NULL for now */
	struct Semaphore MapperAccess;	/* MUST obtain before looking */
					/* at or modifying lists */
	struct List BoardList;
	struct List UnitList;
	struct List MappingList;	/* Note: prioritized */
	
	CPTR Reserved[4]; /* I want a bunch of space for expansion here */
};

#define MAPPERLIB_NAME "mapper.library"
#define MAPPER_VERSION 33

/*
 * 	The MapperBase, SerialBoard and SerialUnit structure lists should
 * 	remain in memory after creation.  The Mapping structures can be
 *	released, note the name was obtained by AllocMem(strlen(name)+1,
 *	MEMF_PUBLIC).  Do not release a Mapping structure if the
 *	MapReserved field is non-null (for safe expansion).
 *
 *	To access any of the lists, you MUST obtain the semaphore!!!!
 *
 *	All these structures should be in public memory.  The private data
 *	areas for the drivers are meant for data storage when the driver
 *	isn't loaded (or hasn't been loaded yet.)
 *
 *	The code attached to each icon in the expansion drawer should
 *	create a SerialBoard structure for each board it is handling.
 *	It should create a SerialUnit structure for each unit on the
 *	board.  Finally, it should create a Mapping structure for each
 *	mapping specified in the icon.  Note: the lists of Mappings are
 *	prioritized, default is 0.
 *
 *	The syntax for the tooltypes in the icons is:
 *		<name>     := <non-whitespace chars excluding ':'>;
 *			     /* should these be case sensitive? */
 *			     /* if so, what about foreign languages? */
 *			     /* should whitespace be allowed? */
 *		<mapping>  := <name>[:<priority>];
 *		<tooltype> := Unit_<number>=<mapping>[|<mapping>...]
 *
 *	General flowchart for expansion drawer code:
 *		<init>
 *		<open mapper library>
 *		<if open failed> {
 *			<create library, then open>
 *			<create XSER: handler entry in handler list>
 *		}
 *		<Obtain semaphore for lists>
 *		<GetDiskObject for the tooltypes>
 *		<for each board you will handle> {
 *			<do any board init needed>
 *			<mark board as configed>
 *			<create and add SerialBoard struct>
 *			<for each unit> {
 *				<create and add SerialUnit struct>
 *				<for each mapping for the unit> {
 *					<create and add Mapping struct>
 *				}
 *			}
 *		}
 *		<release semaphore, close mapper library>
 *		<do anything else you want>
 *		<clean up, release stuff like libraries>
 *		<if driver not loaded now and not in rom>
 *			<return NULL>
 *		<else do whatever, return non-NULL>
 *
 */
     //	Randell Jesup			      Lunge Software Development
    //	Dedicated Amiga Programmer            13 Frear Ave, Troy, NY 12180
 \\//	beowulf!lunge!jesup@steinmetz.UUCP    (518) 272-2942
  \/    (uunet!steinmetz!beowulf!lunge!jesup) BIX: rjesup

michael@.UUCP (Michael) (01/19/88)

In article <197@imagine.PAWL.RPI.EDU> beowulf!lunge!jesup@steinmetz.UUCP writes:
>	You said yourself you planned to have a name-mapper, that maps names
>to unit numbers.  If you have that, why not something that maps names to
>device/unit number pairs?  I think no user should EVER have to care about
>unit numbers, just about what piece of hardware they attached to which board.
>Terminal programs would default to opening 'modem', which of course the user
>could change.  This way, when the user got a new program that uses a modem,

Better: Have each program try to open something based on its name, i.e.
a-talk-plus would open "a-talk-modem", vt100-2.9 would open vt100-modem
(or something like that). The name server would be able to handle duplicates,
i.e. both of those could translate to serial.device, unit 0. Or it could
be "multiplex.device, unit 0" and "unit 1". Or so on. (Who needs more serial
ports with good software underneath? :-)).
				Michael
-- 
: Michael Gersten		ihnp4!hermix!ucla-an!remsit!stb!michael
:				uunet!scgvaxd!stb!michael
: "A hacker lives forever, but not so his free time"

peter@nuchat.UUCP (Peter da Silva) (01/31/88)

Hi! It's me again. The voice crying in the wilderness, you know?

You're all solving something that isn't a problem.

What is wrong with specifying the device name and unit number to the
program that's using the serial port? You can hide it in a prefs type
program if you want, you know.

Perhaps the new serial port should be set up so that you can...

	(a) get the DeviceProc of SERx: (or a device assigned to it).
	(b) Send an ACTION_DISK_INFO.
	(c) Look in the volume entry (just like you do with console.device)
	    for an exec device message port.

AmigaDOS is a nameserver already. Let's not add another one!
-- 
-- a clone of Peter (have you hugged your wolf today) da Silva  `-_-'
-- normally  ...!hoptoad!academ!uhnix1!sugar!peter                U
-- Disclaimer: These aren't mere opinions... these are *values*.

U613127@HNYKUN11.BITNET (Olaf Seibert) (02/05/88)

I have another idea regarding extra serial boards.

Just create a utility to dynamically permutate the unit numbers of
several serial ports.
If you use a program that only knows about unit 0: Fine, give the port
you want it to open the number 0 and start the program.
If you have another such program, just swap unit numbers and the second
program can also have unit 0, but another one. Just make sure the
serial IO requests are properly initialized, so the IO requests can
be related to the correct physical port.  This means that different
ports should have unique device pointers, or unique unit pointers,
even if their unit NUMBERS are nor unique. [ I do not have the RKM
handy, but I think you get Unit pointers in your serial IO
Request. If only the unit number makes it into the Request, the juggler
can change the 0 in it to the real unit number ]  In any case, no serial
device driver needs to be changed to support this juggler, whether it
supports only one unit, or more than one.
You can also have the option to make the jugging automatic. That could
mean something like: If you open unit 0, you get the first available
unit. This is of course only suitable for programs that keep the
port open all the time they may need it, and close it only after
they are all done.
After some time, all programs know that there may be more than one
serial port, and that they may even have a name other than serial.device,
and you can dispose of the unit number juggler.

How about this?
Pro:*No change necessary in existing programs.
     Only the juggler needs to be aware of the file names for the different
       port drivers. Of course, it would be best if one driver drives
       all ports.
    *If done properly, no preloading needed of drivers OR resident lists.
    *I don't have to read ununderstandable pages like 'AllcoConfigDev'
     or something like that.
    *The juggler is optional, but can be kept even when no longer
     needed.

Con:*Propably the juggler needs to juggle with the list of devices.
    *Maybe it can install a fake serial.device ahead of the real one
     to catch all OpenDevices.
    *Maybe it is a little tricky (read: dirty), but its need is not permanent,
     unlike some other proposals.
    *I don't have a modem, a private phone nor a >1st serial port.

Olaf Seibert.