.TH DEVATTACH 10.2.SH NAMEdevattach, devclone, devdir, devgen, devwalk, devdirread, devstat, devopen, devbread, devbwrite, devcreate, devremove, devwstat, devreset, devinit, devshutdown, openmode \- common device driver support.SH SYNOPSIS.ta \w'\fLBlock* 'u +10n.Btypedef int.BDevgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp).PP.BChan* devattach(int tc, char *spec).PP.BChan* devclone(Chan *c).PP.Bvoid devdir(Chan *c, Qid qid, char *n, long length,.B char *user, long perm, Dir *dp).PP.Bint devgen(Chan *c, char *name, Dirtab *tab, int ntab,.B int i, Dir *dp).PP.BWalkqid* devwalk(Chan *c, Chan *nc, char **name, int nname,.B Dirtab *tab, int ntab, Devgen *gen).PP.Bvoid devstat(Chan *c, uchar *db, int n, Dirtab *tab,.B int ntab, Devgen *gen).PP.Blong devdirread(Chan *c, char *d, long n, Dirtab *tab,.B int ntab, Devgen *gen).PP.BChan* devopen(Chan *c, int omode, Dirtab *tab,.B int ntab, Devgen *gen).PP.BBlock* devbread(Chan *c, long n, ulong offset).PP.Blong devbwrite(Chan *c, Block *bp, ulong offset).PP.Bvoid devcreate(Chan*, char*, int, ulong).PP.Bvoid devremove(Chan*).PP.Bvoid devwstat(Chan*, uchar*, int).PP.Bvoid devreset(void).PP.Bvoid devinit(void).PP.Bvoid devshutdown(void).PP.Bint openmode(ulong mode).SH DESCRIPTIONDevice drivers call these functions to carry out essential tasks and default actions.They do most of the name space managementfor a driver that serves a simple name space(eg, data and control files),leaving the driver to concentrate on the device-specific detailsof the I/O requests.More complex drivers also make good use of them at the leavesof their name space, and to help manage the.B Chanstructures correctly..PPA device has an associated.IR type ,represented as a Unicode character (`rune') that identifies the deviceinside and outside the kernel.It appears as the value of the.B typefield in the.B Dirresulting from a.IR sys-stat (2)of any file provided by the device.A device is named outside the kernel usinga path name starting with.B #followed by the device character(eg,.B cin.B #cfor the console).Any subsequent characters beforethe next '/' or end of string is the `device specifier',interpreted solely by the device itself..PP.I Devattachreturns a new channel representingthe root of the file treecorresponding to device type.IR tc ,with device specifier.IR spec .It is normally called by a driver's.I attachfunction (see.IR dev (10.2)).The.B qidfor the new channel is.BR "(Qid){0,0,QTDIR}" ,suitable for a root directory for many devices, buta device driver is free to change it (provided the.B QTDIRbit remains in the.BR Qid.type )..PP.I Devclonereturns a new channel that is a copy of.IR c .An attempt to clone an open channel causes a.IR panic (10.2)..PPThe.L Dirstructure is shown below:.IP.EXtypedefstruct Dir{ /* system-modified data */ ushort type; /* server type */ uint dev; /* server subtype */ /* file data */ Qid qid; /* unique id from server */ ulong mode; /* permissions */ ulong atime; /* last read time */ ulong mtime; /* last write time */ vlong length; /* file length */ char *name; /* last element of path */ char *uid; /* owner name */ char *gid; /* group name */ char *muid; /* last modifier name */} Dir;.EE.PPThis.B Dirstructure corresponds directly to the Limbo.B Diradt described in.IR sys-stat (2)..PPGiven a channel and assorted other information, .I devdirinitialises a Dir structure at.IR dp ..I Devdirsupplies the following data itself:.RS.TF length.TP.B atimelast access time (set to current time).TP.B mtimelast modification time (set to kernel creation date).TP.B gidgroup name (set to.IR eve (10.2)).TP.B lengthlength in bytes (set to zero, whichis normal for most devices).RE.PD.PPNote that.I devdirassigns the values of.I nameand.I userdirectly to fields of.BI * dp,and consequently those values must remain valid until the last use of.BI * dp.(Sometimes that requires the use of an auxiliary buffer, such as.BR up->genbuf .)If channel.I ccorresponds to a file descriptor on which 9P is served,.I devdirsets both the flag bit.B QTMOUNTin.IB dp ->qid.typeand the flag bit.B DMMOUNTin.IB dp ->mode(see.IR sys-export (2)and.I mountin.IR sys-bind (2))..PPA simple name space can be represented in a driver by an array of.B Dirtabstructures.The array is typically static when the names and permissionsare static, but can be dynamically allocated and initialised if required.The structure of.B Dirtabis shown below:.IP.EXtypedefstruct Dirtab{ char name[KNAMELEN]; Qid qid; vlong length; long perm;} Dirtab;.EE.PPThe name.RB ` . '.I mustappear as the first entry in a.B Dirtabif the default.I devgenfunction is used.On the other hand, the name.RB ` .. 'must never appear in a.B Dirtabtable.Drivers that support a directory hierarchy must walk up the hierarchy towardsthe root when their.I walkfunction receives.RB ` .. 'as a file name component.The name.RB ` . 'is never seen by a driver..PPThe.IR devdirread ,.IR devopen ,.IR devstat ,and.IR devwalkfunctions all take a.I genfunction argument,of type.BR Devgen ,which they invoke to retrieve the items ina.B Chanthat represents a directory..I Gentakes a channel.I c(a directory),a file.I name(which is nil except during.IR devwalk ),an array of.B Dirtabstructures.I tabof length.IR ntab ,and a table index.IR i .The functions calling.I genexpect it to place the.IR i 'thentry in the directory into.IR \f5*\fPdp .It should return 1if the call was successful,-1 if.I iis beyond the index of the last directory entry,or 0 if there is no entry at.IR i ,but there are entries beyond it.When.I ihas the special value.B DEVDOTDOTthen.I genshould set.IR \f5*\fPdpto reflect the parent of.IR c ;if.I cis a one-level device directory, then `..' is equivalent to `.'.Custom implementations of.I genoften ignore.IR devtab ,and instead return their own dynamically generatedset of directory entries from some other source.Exceptionally, during.I devwalka non-nil.I nameis provided: it is the name being looked up, and a device-specific.I gencan short-circuit the search by returning -1 if the name does not exist,or filling in.IR \f5*\fPdpand returning 1 if it does exist..PPThe function.I devgenis compatible with.BR Devgen ;it returns the.IR i 'thentry in.IR devtab ,and can be used to provide a simple, staticset of directory entries..PP.I Devwalkwalks channel.I cto the file in the device named by the path encoded in.IR name ,which is an array of strings of length.IR nname .It provides the interface to.IR walk (5)within the kernel, and that specification must be well understood to appreciateall the nuances of its interface.Fortunately, in nearly all device drivers, a device's.I walkfunction typically passes its parameters on to.I devwalk(adding the device's own.B Dirtabarray as the the value of.IR tab ),and simply returning the result of.IR devwalk ..PP.I Devwalkwalks.I cusing the given set of names, and if the walk is successful, thechannel.I ncwill refer to the result of the walk(specifically,.IB nc ->qidis set to the Qid for the file).If.I ncis nil,.I devwalkwill allocate a new channel itself, that is initially a clone of.IR c .As in.IR walk (5),.I devwalkcan return a partial result,represented bya dynamically allocated value of the following structure:.IP.EXstruct Walkqid{ Chan *clone; int nqid; Qid qid[1]; /* actually nname in length */};.EE.PPThe value must be freed after use.For each element of.I name ,.I devwalkpassesthe.I tabparameter to.I gentogether with the currently-sought element of.IR name .If the first element is not found,.I devwalkreturns nil; otherwise, it returns a.B Walkqidvalue in which.B nqidelements of the array.B qidare set to the qids (see.IR intro (5))of each valid element of.IR name .If all.I nnameelements were successfully traversed, then.B nqidwill have the value.IR nname ,and.B clonewill refer to the result of the walk,which is either.I ncif given, orthe new channel allocated by.IR devwalk .Otherwise, at least one element succeeded and.B nqidis less than.I nnameand.B cloneis nil.On an error or incomplete walk,the error string is set to the error that stopped the walk (eg,.B Enonexistor.BR Enotdir )..PP.I Devstatfills the array of bytes.I dbwith data in the format produced by.IR stat (5)that describes the filereferenced by channel.IR c ,which must have a corresponding entryreturned by.IR gen(ie, an entry with matching.BR Qid.path ).If.I cis a communications channel connecting a 9P server to a current mount point,the.B DMMOUNTbit is set in the resulting.BR Dir.mode ,and.B QTMOUNTis set in.BR Dir.qid.type .As in.IR stat (5),the length of the data written to.I dbvaries; if more than.I nbytes are needed,.I devstatraises the.IR error (10.2).BR Ebadarg .Otherwise, it returns the number of bytes in.I dbactually used..PPIf an entry with the desired qid is not found in the table, but.I ccorresponds to a directory(ie,.B QTDIRis set inLines 1–500 of 698. Load more
.TH DEVATTACH 10.2 .SH NAME devattach, devclone, devdir, devgen, devwalk, devdirread, devstat, devopen, devbread, devbwrite, devcreate, devremove, devwstat, devreset, devinit, devshutdown, openmode \- common device driver support .SH SYNOPSIS .ta \w'\fLBlock* 'u +10n .B typedef int .B Devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) .PP .B Chan* devattach(int tc, char *spec) .PP .B Chan* devclone(Chan *c) .PP .B void devdir(Chan *c, Qid qid, char *n, long length, .B char *user, long perm, Dir *dp) .PP .B int devgen(Chan *c, char *name, Dirtab *tab, int ntab, .B int i, Dir *dp) .PP .B Walkqid* devwalk(Chan *c, Chan *nc, char **name, int nname, .B Dirtab *tab, int ntab, Devgen *gen) .PP .B void devstat(Chan *c, uchar *db, int n, Dirtab *tab, .B int ntab, Devgen *gen) .PP .B long devdirread(Chan *c, char *d, long n, Dirtab *tab, .B int ntab, Devgen *gen) .PP .B Chan* devopen(Chan *c, int omode, Dirtab *tab, .B int ntab, Devgen *gen) .PP .B Block* devbread(Chan *c, long n, ulong offset) .PP .B long devbwrite(Chan *c, Block *bp, ulong offset) .PP .B void devcreate(Chan*, char*, int, ulong) .PP .B void devremove(Chan*) .PP .B void devwstat(Chan*, uchar*, int) .PP .B void devreset(void) .PP .B void devinit(void) .PP .B void devshutdown(void) .PP .B int openmode(ulong mode) .SH DESCRIPTION Device drivers call these functions to carry out essential tasks and default actions. They do most of the name space management for a driver that serves a simple name space (eg, data and control files), leaving the driver to concentrate on the device-specific details of the I/O requests. More complex drivers also make good use of them at the leaves of their name space, and to help manage the .B Chan structures correctly. .PP A device has an associated .IR type , represented as a Unicode character (`rune') that identifies the device inside and outside the kernel. It appears as the value of the .B type field in the .B Dir resulting from a .IR sys-stat (2) of any file provided by the device. A device is named outside the kernel using a path name starting with .B # followed by the device character (eg, .B c in .B #c for the console). Any subsequent characters before the next '/' or end of string is the `device specifier', interpreted solely by the device itself. .PP .I Devattach returns a new channel representing the root of the file tree corresponding to device type .IR tc , with device specifier .IR spec . It is normally called by a driver's .I attach function (see .IR dev (10.2)). The .B qid for the new channel is .BR "(Qid){0,0,QTDIR}" , suitable for a root directory for many devices, but a device driver is free to change it (provided the .B QTDIR bit remains in the .BR Qid.type ). .PP .I Devclone returns a new channel that is a copy of .IR c . An attempt to clone an open channel causes a .IR panic (10.2). .PP The .L Dir structure is shown below: .IP .EX typedef struct Dir { /* system-modified data */ ushort type; /* server type */ uint dev; /* server subtype */ /* file data */ Qid qid; /* unique id from server */ ulong mode; /* permissions */ ulong atime; /* last read time */ ulong mtime; /* last write time */ vlong length; /* file length */ char *name; /* last element of path */ char *uid; /* owner name */ char *gid; /* group name */ char *muid; /* last modifier name */ } Dir; .EE .PP This .B Dir structure corresponds directly to the Limbo .B Dir adt described in .IR sys-stat (2). .PP Given a channel and assorted other information, .I devdir initialises a Dir structure at .IR dp . .I Devdir supplies the following data itself: .RS .TF length .TP .B atime last access time (set to current time) .TP .B mtime last modification time (set to kernel creation date) .TP .B gid group name (set to .IR eve (10.2)) .TP .B length length in bytes (set to zero, which is normal for most devices) .RE .PD .PP Note that .I devdir assigns the values of .I name and .I user directly to fields of .BI * dp, and consequently those values must remain valid until the last use of .BI * dp. (Sometimes that requires the use of an auxiliary buffer, such as .BR up->genbuf .) If channel .I c corresponds to a file descriptor on which 9P is served, .I devdir sets both the flag bit .B QTMOUNT in .IB dp ->qid.type and the flag bit .B DMMOUNT in .IB dp ->mode (see .IR sys-export (2) and .I mount in .IR sys-bind (2)). .PP A simple name space can be represented in a driver by an array of .B Dirtab structures. The array is typically static when the names and permissions are static, but can be dynamically allocated and initialised if required. The structure of .B Dirtab is shown below: .IP .EX typedef struct Dirtab { char name[KNAMELEN]; Qid qid; vlong length; long perm; } Dirtab; .EE .PP The name .RB ` . ' .I must appear as the first entry in a .B Dirtab if the default .I devgen function is used. On the other hand, the name .RB ` .. ' must never appear in a .B Dirtab table. Drivers that support a directory hierarchy must walk up the hierarchy towards the root when their .I walk function receives .RB ` .. ' as a file name component. The name .RB ` . ' is never seen by a driver. .PP The .IR devdirread , .IR devopen , .IR devstat , and .IR devwalk functions all take a .I gen function argument, of type .BR Devgen , which they invoke to retrieve the items in a .B Chan that represents a directory. .I Gen takes a channel .I c (a directory), a file .I name (which is nil except during .IR devwalk ), an array of .B Dirtab structures .I tab of length .IR ntab , and a table index .IR i . The functions calling .I gen expect it to place the .IR i 'th entry in the directory into .IR \f5*\fPdp . It should return 1 if the call was successful, -1 if .I i is beyond the index of the last directory entry, or 0 if there is no entry at .IR i , but there are entries beyond it. When .I i has the special value .B DEVDOTDOT then .I gen should set .IR \f5*\fPdp to reflect the parent of .IR c ; if .I c is a one-level device directory, then `..' is equivalent to `.'. Custom implementations of .I gen often ignore .IR devtab , and instead return their own dynamically generated set of directory entries from some other source. Exceptionally, during .I devwalk a non-nil .I name is provided: it is the name being looked up, and a device-specific .I gen can short-circuit the search by returning -1 if the name does not exist, or filling in .IR \f5*\fPdp and returning 1 if it does exist. .PP The function .I devgen is compatible with .BR Devgen ; it returns the .IR i 'th entry in .IR devtab , and can be used to provide a simple, static set of directory entries. .PP .I Devwalk walks channel .I c to the file in the device named by the path encoded in .IR name , which is an array of strings of length .IR nname . It provides the interface to .IR walk (5) within the kernel, and that specification must be well understood to appreciate all the nuances of its interface. Fortunately, in nearly all device drivers, a device's .I walk function typically passes its parameters on to .I devwalk (adding the device's own .B Dirtab array as the the value of .IR tab ), and simply returning the result of .IR devwalk . .PP .I Devwalk walks .I c using the given set of names, and if the walk is successful, the channel .I nc will refer to the result of the walk (specifically, .IB nc ->qid is set to the Qid for the file). If .I nc is nil, .I devwalk will allocate a new channel itself, that is initially a clone of .IR c . As in .IR walk (5), .I devwalk can return a partial result, represented by a dynamically allocated value of the following structure: .IP .EX struct Walkqid { Chan *clone; int nqid; Qid qid[1]; /* actually nname in length */ }; .EE .PP The value must be freed after use. For each element of .I name , .I devwalk passes the .I tab parameter to .I gen together with the currently-sought element of .IR name . If the first element is not found, .I devwalk returns nil; otherwise, it returns a .B Walkqid value in which .B nqid elements of the array .B qid are set to the qids (see .IR intro (5)) of each valid element of .IR name . If all .I nname elements were successfully traversed, then .B nqid will have the value .IR nname , and .B clone will refer to the result of the walk, which is either .I nc if given, or the new channel allocated by .IR devwalk . Otherwise, at least one element succeeded and .B nqid is less than .I nname and .B clone is nil. On an error or incomplete walk, the error string is set to the error that stopped the walk (eg, .B Enonexist or .BR Enotdir ). .PP .I Devstat fills the array of bytes .I db with data in the format produced by .IR stat (5) that describes the file referenced by channel .IR c , which must have a corresponding entry returned by .IR gen (ie, an entry with matching .BR Qid.path ). If .I c is a communications channel connecting a 9P server to a current mount point, the .B DMMOUNT bit is set in the resulting .BR Dir.mode , and .B QTMOUNT is set in .BR Dir.qid.type . As in .IR stat (5), the length of the data written to .I db varies; if more than .I n bytes are needed, .I devstat raises the .IR error (10.2) .BR Ebadarg . Otherwise, it returns the number of bytes in .I db actually used. .PP If an entry with the desired qid is not found in the table, but .I c corresponds to a directory (ie, .B QTDIR is set in