From owner-freebsd-hackers Wed Jan 29 22:02:01 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id WAA22121 for hackers-outgoing; Wed, 29 Jan 1997 22:02:01 -0800 (PST) Received: from genesis.atrad.adelaide.edu.au (genesis.atrad.adelaide.edu.au [129.127.96.120]) by freefall.freebsd.org (8.8.5/8.8.5) with ESMTP id WAA22113 for ; Wed, 29 Jan 1997 22:01:55 -0800 (PST) Received: (from msmith@localhost) by genesis.atrad.adelaide.edu.au (8.8.2/8.7.3) id QAA27658; Thu, 30 Jan 1997 16:31:39 +1030 (CST) From: Michael Smith Message-Id: <199701300601.QAA27658@genesis.atrad.adelaide.edu.au> Subject: Device Drivers 101 In-Reply-To: <199701300505.AAA09649@spoon.beta.com> from "Brian J. McGovern" at "Jan 30, 97 00:05:43 am" To: mcgovern@spoon.beta.com (Brian J. McGovern) Date: Thu, 30 Jan 1997 16:31:38 +1030 (CST) Cc: msmith@atrad.adelaide.edu.au, hackers@freebsd.org X-Mailer: ELM [version 2.4ME+ PL28 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: owner-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk Brian J. McGovern stands accused of saying: > > >Driver initialisation is seperated into two parts, known as 'probe' and > >'attach'. The purpose of the 'probe' routine is to ascertain whether > >the hardware is present, and optionally determine its configuration. > > >Probe/attach for ISA device drivers is triggered by the presence of a > >non-static isa_driver structure in the driver; at least the first three > >fields should be initialised, with the probe and attach routines and the > >name of the driver : > > Ok. I know the what. Any particular reason it has to be non-static? I assume > to cause it to blow up if there is another driver with the same name, but, > am I correct? The structures are collated at link time into what is known as a 'linker set'. This results in a statically-initialised array of all of the isa_device structures which can be processed by the startup code. The structure has to be non-static so that it is visible to the linker. > Secondly, what are the fields after the first 3? There is only one other field at the moment : struct isa_driver { int (*probe) __P((struct isa_device *idp)); /* test whether device is present */ int (*attach) __P((struct isa_device *idp)); /* setup driver for a device */ char *name; /* device name */ int sensitive_hw; /* true if other probes confuse us */ } Drivers with sensitive_hw set to true are probed before others to avoid being confused by other probes to the same space. > Also, I did a grep for "isa_driver" in /usr/include via a find (ie - > grep "isa_driver" `find .` to no avail. Which header should I include? #include , found in /sys/i386/isa/. As a kernel-only header, it't not found under /usr/include. > >struct isa_driver foodriver = { fooprobe, fooattach, "foo"}; > > >The 'fooprobe' function is called during startup to determine whether > >the device is present or not. It should return zero if the probe > >for the hardware failed, or the size of the I/O space occupied by > >the device if the probe succeeded. > > Please define "size of the I/O space". To me, this can mean many > things, probably all of which are wrong. Is it the number of ports a > device uses? Amount of memory (shared or otherwise)? And how about > our simulated pseudo device, which won't control hardware, but might > have a few K in buffers? The size of the range of I/O ports that the device occupies. This is, as has been observed elsewhere, a poor choice, as there are devices that occupy no I/O ports, and others that occupy several disjoint ranges. Pseudo-devices are handled differently. The 'vn' driver is a good place to look for a readable example (/sys/dev/vn/vn.c), but the basic strategy involves using the SYSINIT macro to register a startup function which calls the pseudo-device's init function, which in turn uses [cb]devsw_add and optionally devfs_add* to register the driver's existence. (For "normal" devices, the bus probe code for the bus to which the device belongs processes the linker set described above and calls the probe/attach pairs.) > >It is legitimate to alter the contents of the fields in the isa_device > >structure, if new values are determined by probing for the hardware. > >Note that the id_irq field is a bitmask, not a numeric value. The > >probe routine should not emit any text unless it comes up against > >something particularly alarming. > > Ok. id_irq is a bitmask. I'll have to save my other questions once I can > find struct isa_device. I am currently assuming that this contains the > info in the kernel config file when called. Same for a pseudo-device? Pseudo-devices don't get any config information. The isa_device structure is initialised by the config file data, yes. > >Attach is called, again once per instance of the driver in the config, > >when the device has been successfully probed and does not conflict. > Does the driver make the call as to the conflict? Or does the system look > at the struct isa_device, and if a conflict occurs, not call the probe > and attach routines? The bus code is responsible for deciding whether a driver is in conflict; drivers should ideally know nothing about the bus or other drivers. > >Once internal state for the driver has been established, you add an entry > >to the device switch for the driver. In the case of a character device, > >the following fragment is normally used : > > > > dev = makedev(CDEV_MAJOR,0); > > cdevsw_add(&dev,&foo_cdevsw,NULL); > > > > Ok. Looks clear enough. I'm assuming we're still in attach here... I'm > also assuming that block devices would call bdevsw_add (wrong name i think, > but I think I get the idea). The name is correct too 8) > How about STREAMS types or tty type devices that are linked off > through a line protocol? No STREAMS in the BSD kernel 8). Tty devices are character devices; there's extra state involved in interacting with the tty stack, which is logically layered on top of the character driver. This is a topic on which Bruce is best qualified to comment; I'm just going to refer to sio.c and translate what I read into English 8) > >Where CDEV_MAJOR is the major device number assigned to the driver > >(normally #defined somewhere obvious). > > > >A typical cdevsw initialisation might look like : > > > >static d_open_t fooopen; > >static d_close_t fooclose; > >static d_read_t fooread; > >static d_write_t foowrite; > >static d_ioctl_t fooioctl; > >static d_select_t fooselect; > > > >#define CDEV_MAJOR 20 > >static struct cdevsw foo_cdevsw = > >{ > > fooopen, fooclose, fooread, foowrite, > > fooioctl, nullstop, nullreset, nodevtotty, > > fooselect, nommap, NULL, driver_name, > > NULL, -1 > >}; > > > > Ok. Some of it makes sense. Is there a blank generic one that gives the > appropriate order? For instance, I see nullstop and nullreset. There should > also be a poll routine in there some where? Is it a NULL? a no? a -1? I don't believe that there's a blank. The structure and the blanks are listed in /sys/sys/conf.h. I should have been a little more thoughtful about the no vs. null comment : The no* versions return ENODEV, the null* versions always succeed but do nothing, the nx* versions return ENXIO (but are a bad idea according to the comment in sys/kern/subr_xxx.c where they are defined). BSD doesn't have a poll syscall; 'similar' functionality is afforded by select(2). > Ok. Is creating a devfs node mandatory? I know people would like to move to > it, but when/is it required? What makes the decision if it is optional? It's not mandatory, but if you don't put a call in to create it, someone else will 8) Normally devfs node creation is conditionalised on DEVFS. > >You can call this several times to create multiple nodes for a single > >instance of the driver. > > Ok. I assume this means that it'll generate the same major numbers with > appropriate minor numbers? Devfs doesn't really 'do' major and minor numbers; there's a logically direct translation from the named node to your switch entry and the unit number you supply when you create the node. -- ]] Mike Smith, Software Engineer msmith@gsoft.com.au [[ ]] Genesis Software genesis@gsoft.com.au [[ ]] High-speed data acquisition and (GSM mobile) 0411-222-496 [[ ]] realtime instrument control. (ph) +61-8-8267-3493 [[ ]] Unix hardware collector. "Where are your PEZ?" The Tick [[