On Tue, Feb 09, 2010 at 04:05:00PM -0800, Ira W. Snyder wrote:
> Hello all,
> 
> I posted last week asking about a driver for boards running on a PLX
> chip. It turns out that these are passive boards. I have been looking
> for a driver for the Janz CMOD-IO board CAN interfaces.
> 
> I finally found the datasheets and took the time to write a driver. This
> board is an intelligent CAN interface: it has onboard microprocessors to
> help process CAN traffic.
> 
> This is a very rough first try at a CAN driver. I'm sure it still has
> problems, and I would appreciate if you can take a look and help me add
> what is needed. I'm am not extremely knowledgeable about the CAN bus.
> 
> The things that are known to be wrong:
> 
> - bus-on / bus-off handling
> 
> I did this straight in the network device open()/stop() methods. I don't
> handle the condition where we get too many bus errors and the bus goes
> into bus-off state. What should I be doing here?
What you call 'bus-off' is indeed the stop() method. the CAN busoff
(which is something different)
comes via interrupt (bus-state-change), indicating the
can-chip cut itself from the bus. In such case, a special 'struct
can_frame' must be emitted to userspace.
> 
> - state changes, bit timing, etc.
the bittiming looks exactly as SJA1000 (especially the resulting
      register values). please take a look there.
> 
> I'm not at all sure how this is supposed to work. Perhaps someone that
> knows CAN bus better that I do can help.
The bittiming is calculated (in drivers/net/can/dev.c) from the
constants you provide. again, sja1000 is a 'reference'.
opening/closing:
from userspace, the open() gets called somehow. You will activate the
can chip (what you called 'bus-on', which is a strange terminology IMHO).
can messages come & go now. When there are distortions on the CAN bus,
    the CAN chip will raise some errors (via interrupts). At a certain
    point, distortions get so bad and the can chip cuts itself from the
    bus (accompanied by an interrupt, as mentioned above).
    You are not supposed to call close() there.
> 
> - CAN bus termination
> 
> This board supports optionally terminating the CAN bus. In order to test
> this driver, I connected both CAN modules on a single board together. To
> get this to work, I needed to turn on termination on both modules.
> 
> Is this wrong?
A bus must have both ends terminated (although a labo setup will do with
      1 termination too). The idea is that not every 'node' in the
middle must terminate the bus, only the endpoints.
What you did seems right.
> Is there a way to enable/disable termination via the "ip"
> tool?
There is at this point no such thing yet. Such properties may be enabled
via sysfs IMHO.
> 
> - module probing
> 
> This board is really a MODULbus carrier board, into which plugs 4
> daughterboards. These can be CAN modules, or others. On my board, I have
> 2x CAN modules and 1x TTL GPIO module. I need support for both of these
> for my application. For the time being, I *did not* add support for the
> TTL module. That will come once the CAN part is finished.
> 
> Also, there is no way I am aware of to determine what type of board is
> plugged into which MODULbus slot on the carrier board. My CAN modules
> support identification, but the TTL module does not.
> 
> I hard-coded the module layout into the driver itself. This is
> sufficient for my purposes, but probably is not sufficient for mainline
> Linux :'(. Any ideas or suggestions?
I would (but I'm not authoring this) construct a PCI driver for the
carrier board, with 4 platform devices. During probe of the PCI drivers,
you can tweak the ID's of the platform devices.
Next, you create seperate drivers: CAN, TTL, ....
in drivers/mfd, you'll find some examples of what I try to explain.

You will have to provide some access methods for the platform_devices.
That's where you will link daughterboards to carrier board.

And to make life simpler, you can create bigger structs for the
platform_device, as in:

struct janz_device {
   struct platform_device pdev;
   struct pci_device *carrier;
   int (*reg_rd)(struct janz_device *, etc ...);
   void (*reg_wr)(struct janz_device *, etc ...);
   ....
};
#defien platform_to_janz(x) container_of(x, struct janz_device, pdev)

As such, a clean seperation can be made between the carrier board & the
differen daughter boards.

> 
> 
> Any review will be much appreciated!
Did not get there in detail :-)
Kurt
> 
> Thanks,
> Ira
_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to