/* $Header: $ */ #define _DDI_DKI 1 #define _SYSV4 1 /* * Routines for manipulating device numbers. * * System V defines "dev_t" as 32-bit, which makes some things problematic * when attempting to run SVR4 drivers in an iBCS2 environment. The concept * of external and internal numbers, introduced at the same time as the 32- * bit "dev_t", provides an effective solution. * * This is of primary importance to clone devices which may want to support * more than 256 connections, but any driver which wants or needs to encode * more that 8 bits of information in the minor number may also benefit from * use of the external/internal mapping regime. * * $Log: $ */ /* *-IMPORTS: * <sys/types.h> * dev_t * <limits.h> * CHAR_BIT */ #include <sys/types.h> #include <limits.h> /* * Define this symbol to make the code in this module ignore the _max_minor, * _major [], and _minor [] configuration tables, and simply map internal and * external major and minor numbers one-to-one. */ /* #define ONE_TO_ONE */ /* * If we are dealing with a situation where we are trying to run DDI/DKI code * side-by-side with code that uses a different "dev_t", we rely on a layer * that can may the pre-SVR4 or alien calling sequence for the DDI/DKI entry * points. This code must deal with converting the old-style "dev_t" to a * new-style "dev_t" and vice-versa. * * In particular, if a device generates a minor number outside the range of * precision of the old-style system, the mapping layer must use these * functions to select an appropriate major number to overflow to. */ #define DSHIFT (sizeof (dev_t) * CHAR_BIT / 2) #define GETEMAJOR(dev) ((major_t) ((dev) >> DSHIFT)) #define GETEMINOR(dev) ((minor_t) ((dev) & ~ (1L << DSHIFT))) #define MAKEDEVICE(maj,min) (((dev_t) (maj) << DSHIFT) + (min)) /* * The following external reference is to a table generated by the kernel * configuration process for all the devices configured in the system. It * defines a many-to-one mapping between external and internal major device * numbers. * * This mapping can also affect internal device numbers; for instance, * external major device 10, minor 5 might map to internal 2, minor 30. */ #ifndef ONE_TO_ONE extern major_t _maxmajor; extern major_t _major []; /* internal major number for external major */ extern minor_t _minor []; /* value added to external minor number */ #endif /* *-STATUS: * DDI/DKI * *-NAME: * etoimajor Convert external to internal major device number. * *-SYNOPSIS: * #include <sys/types.h> * #include <sys/ddi.h> * * major_t etoimajor (major_t emaj); * *-ARGUMENTS: * emaj External major number. * *-DESCRIPTION: * etoimajor () converts the external major number (emaj) to an internal * major number. See getemajor () for a description of external and * internal major numbers. * *-RETURN VALUE: * etoimajor () returns the internal major number or NODEV if the * external major number is not valid. * *-LEVEL: * Base or interrupt. * *-NOTES: * Does not sleep. * * Driver-defined basic locks, read/write locks, and sleep locks may be * held across calls to this function. * *-SEE ALSO: * getemajor (), geteminor (), getmajor (), getminor (), itoemajor (), * makedevice (). */ #if __USE_PROTO__ major_t (etoimajor) (major_t emaj) #else major_t etoimajor __ARGS ((emaj)) major_t emaj; #endif { #ifdef ONE_TO_ONE return emaj; #else return (emaj >= _maxmajor ? NODEV : _major [emaj]); #endif } /* *-STATUS: * DDI/DKI * *-NAME: * getemajor Get external major device number. * *-SYNOPSIS: * #include <sys/types.h> * #include <sys/ddi.h> * * major_t getemajor (dev_t dev); * *-ARGUMENTS: * dev External device number. * *-DESCRIPTION: * getemajor () returns the external major number given a device number, * "dev". External major numbers are visible to the user. Internal major * numbers are only visible in the kernel. Since the range of major * numbers may be large and sparsely populated, the kernel keeps a * mapping between external and internal major numbers to save space. * * All driver entry points are passed device numbers using external * major numbers. * * Usually, a driver with more than one external major number will have * only one internal major number. However, some system implementations * map one-to-one between internal and external major numbers. Here, the * internal major number is the same as the external major number and the * driver may have more than one internal major number. * *-RETURN VALUE: * The external major number. * *-LEVEL: * Base or interrupt. * *-NOTES: * Does not sleep. * * Driver-defined basic locks, read/write locks, and sleep locks may be * held across calls to this function. * *-SEE ALSO: * etoimajor (), geteminor (), getmajor (), getminor (), makedevice (). */ #if __USE_PROTO__ major_t (getemajor) (n_dev_t dev) #else major_t getemajor __ARGS ((dev)) n_dev_t dev; #endif { return GETEMAJOR (dev); } /* *-STATUS: * DDI/DKI * *-NAME: * geteminor Get external minor device number. * *-SYNOPSIS: * #include <sys/types.h> * #include <sys/ddi.h> * * minor_t geteminor (dev_t dev); * *-ARGUMENTS: * dev External device number. * *-DESCRIPTION: * geteminor () returns the external minor number given a device number, * "dev". External minor numbers are visible to the user. Internal minor * numbers are only visible in the kernel. Since a driver can support * more than one external major device that maps to the same internal * major device, the kernel keeps a mapping between external minor * numbers and internal minor numbers to allow drivers to index arrays * more easily. For example, a driver may support two devices, each with * five minor numbers. The user may see each set of minor numbers * numbered from zero to four, but the driver sees them as one set of * minor numbers numbered zero to nine. * * All driver entry points are passed device numbers using external minor * numbers. * * Systems that map external major numbers one-to-one with internal major * numbers also map external minor numbers one-to-one with internal minor * numbers. * *-RETURN VALUE: * The external minor number. * *-LEVEL: * Base or interrupt. * *-NOTES: * Does not sleep. * * Driver-defined basic locks, read/write locks, and sleep locks may be * held across calls to this function. * *-SEE ALSO: * etoimajor (), getemajor (), getmajor (), getminor (), makedevice () */ #if __USE_PROTO__ minor_t (geteminor) (n_dev_t dev) #else minor_t geteminor __ARGS ((dev)) n_dev_t dev; #endif { return GETEMINOR (dev); } /* *-STATUS: * DDI/DKI * *-NAME: * getmajor Get internal major device number. * *-SYNOPSIS: * #include <sys/types.h> * #include <sys/ddi.h> * * major_t getemajor (dev_t dev); * *-ARGUMENTS: * dev Device number. * *-DESCRIPTION: * The getmajor () function extracts the internal major number from a * device number. See getemajor () for an explanation of external and * internal major numbers. * *-RETURN VALUE: * The internal major number. * *-LEVEL: * Base or interrupt. * *-NOTES: * No validity checking is performed. If "dev" is invalid, an invalid * number is returned. * * Does not sleep. * * Driver-defined basic locks, read/write locks, and sleep locks may be * held across calls to this function. * *-SEE ALSO: * etoimajor (), getemajor (), geteminor (), getminor (), makedevice () */ #if __USE_PROTO__ major_t (getmajor) (n_dev_t dev) #else major_t getmajor __ARGS ((dev)) n_dev_t dev; #endif { #ifdef ONE_TO_ONE return GETEMAJOR (dev); #else return _major [GETEMAJOR (dev)]; #endif } /* *-STATUS: * DDI/DKI * *-NAME: * getminor Get internal minor device number. * *-SYNOPSIS: * #include <sys/types.h> * #include <sys/ddi.h> * * minor_t getminor (dev_t dev); * *-ARGUMENTS: * dev Device number. * *-DESCRIPTION: * The getminor () function extracts the internal minor number from a * device number. See getemajor () for an explanation of external and * internal major numbers. * *-RETURN VALUE: * The internal minor number. * *-LEVEL: * Base or interrupt. * *-NOTES: * No validity checking is performed. If "dev" is invalid, an invalid * number is returned. * * Does not sleep. * * Driver-defined basic locks, read/write locks, and sleep locks may be * held across calls to this function. * *-SEE ALSO: * etoimajor (), getemajor (), geteminor (), getmajor (), makedevice () */ #if __USE_PROTO__ minor_t (getminor) (n_dev_t dev) #else minor_t getminor __ARGS ((dev)) n_dev_t dev; #endif { #ifdef ONE_TO_ONE return GETEMINOR (dev); #else return GETEMINOR (dev) + _minor [GETEMAJOR (dev)]; #endif } /* *-STATUS: * DDI/DKI * *-NAME: * itoemajor Convert internal to external major number. * *-SYNOPSIS: * #include <sys/types.h> * #include <sys/ddi.h> * * major_t itoemajor (major_t imaj, major_t prevemaj); * *-ARGUMENTS: * imaj Internal major number. * * prevemaj Most recently obtained external major number (or * NODEV, if this is the first time the function has been * called). * *-DESCRIPTION: * itoemajor () converts the internal major number to the external major * number. The external-to-internal major number mapping can be many-to- * one, and so any internal major number may correspond to more than one * external major number. By repeatedly invoking this function, the * driver can obtain all possible external major number values. See * getemajor () for an explanation of external and internal major * numbers. * *-RETURN VALUE: * External major number, or NODEV if all have been searched. * *-LEVEL: * Base or interrupt. * *-NOTES: * Does not sleep. * * Driver-defined basic locks, read/write locks, and sleep locks may be * held across calls to this function. * *-SEE ALSO: * etoimajor (), getemajor (), geteminor (), getmajor (), getminor (), * makedevice () */ #if __USE_PROTO__ major_t (itoemajor) (major_t imaj, major_t prevemaj) #else major_t itoemajor __ARGS ((imaj, prevemaj)) major_t imaj; major_t prevemaj; #endif { #ifdef ONE_TO_ONE return prevemaj == NODEV ? imaj : NODEV; #else if (prevemaj == NODEV) prevemaj = 0; else prevemaj ++; while (prevemaj ++ < _maxmajor) if (_major [prevemaj] == imaj) return prevemaj; return NODEV; #endif } /* *-STATUS: * DDI/DKI * *-NAME: * makedevice Make device number from major and minor numbers. * *-SYNOPSIS: * #include <sys/types.h> * #include <sys/ddi.h> * * dev_t makedevice (major_t majnum, minor_t minnum); * *-ARGUMENTS: * majnum Major number. * * minnum Minor number. * *-DESCRIPTION: * The makedevice () function creates a device number from a major and * minor device number. makedevice () should be used to create device * numbers so that the driver will port easily to releases that treat * device numbers differently. * *-RETURN VALUE: * The device number, containing both the major number and the minor * number, is returned. No validation of the major or number numbers is * performed. * *-LEVEL: * Base or interrupt. * *-NOTES: * Does not sleep. * * Driver-defined basic locks, read/write locks, and sleep locks may be * held across calls to this function. * *-SEE ALSO: * getemajor (), geteminor (), getmajor (), getminor () */ #if __USE_PROTO__ n_dev_t (makedevice) (major_t majnum, minor_t minnum) #else n_dev_t makedevice __ARGS ((majnum, minnum)) major_t majnum; minor_t minnum; #endif { return MAKEDEVICE (majnum, minnum); }