2da1605875ca816b423b46de952a58e8074d6b8d
[dragonfly.git] / notes / porting_drivers.txt
1 $DragonFly: doc/notes/porting_drivers.txt,v 1.4 2008/04/06 19:08:30 pavalos Exp $
2
3                     PORTING FREEBSD DRIVERS TO DRAGONFLY
4
5 * Copy the driver code to the appropriate DragonFly directory.  For example,
6   a disk driver /usr/src/sys/dev/blah in FreeBSD would likely be 
7   /usr/src/sys/dev/disk/blah in DragonFly.
8
9 * Keep all the CVS ids in the files for future reference point. If the files
10   don't have it, please add it to them. You can find them out from CVSWeb
11   repository or by checking out the specific source files with the FreeBSD
12   SVN client.
13   This could be automated in the case pkgsrc's SVN client had the set of
14   patches that provide this functionality.
15
16 * Try to keep all the CVS ids from FreeBSD for future reference. You can
17   get them by checking out the related source files with the FreeBSD SVN
18   client or having a look at their cvsweb site. A permanent solution for
19   this issue would be to patch pkgsrc's SVN client with FreeBSD patches to
20   get the IDs properly handled automatically.
21
22 * Remove FBSDID declaration and '#include <sys/cdefs.h>' as well.
23
24 * Driver local #include's probably use a <dev/blah/blah.h> path.  These
25   need to be changed to "blah.h".   '.' is not included in the #include
26   path in FreeBSD builds, but it is in DragonFly builds.
27
28 * Other #include's may reference things in <dev/...> which in DragonFly
29   reside in <bus/...>.  In particular, dev/pccard becomes bus/pccard.
30   Note that defines in FreeBSD's pccard_cis.h reside in DragonFly's
31   pccardreg.h .
32
33 * The following kernel functions have been renamed in DragonFly:
34
35   malloc(), free() etc. ->      kmalloc(), kfree() etc.
36   printf() etc.         ->      kprintf() etc.
37   psignal()             ->      ksignal()
38   random()              ->      krandom()
39
40 * MUTEX conversion - mutexes are generally replaced by spinlocks.  However,
41   DragonFly spinlocks are more restrictive than FreeBSD mutexes so a
42   direct replacement is not necessarily appropriate in all cases.  A lockmgr
43   lock should be used when a direct replacement is not appropriate.
44   In particular, DragonFly does not allow recursive exclusive spinlocks
45   and does not allow multiple exclusive spinlocks to be held by any given
46   thread.
47
48   Instances of <sys/mutex.h> should be replaced with <sys/spinlock.h>.
49
50   When replacing mutexes with spinlocks it is a good idea to rename 
51   the structural field (typically 'mtx') to something else (typically 'spin').
52
53   The &Giant mutex is typically converted to get_mplock() and rel_mplock().
54   However, there are places where FreeBSD unlocks giant around some code and
55   then relocks giant... those should simply be removed.
56
57   FreeBSD has weird callout + mutex functions.  DragonFly does not integrate
58   the two.  Instead, the driver in DragonFly must obtain the spinlocks
59   in question in the callback routine.
60
61   As a rule of thumb, MTX_DEF mutexes should be replaced with exclusive,
62   recursive lockmgr locks.
63
64   So, suppose the original code is using 
65         struct mtx my_mtx;
66   you'd normally rename it to
67         struct lock my_lock;
68
69   and change the initialization from something like
70         mtx_init(&my_mtx, "mymtx", "whatever", MTX_DEF);
71   to
72         lockinit(&my_lock, "mylock", 0, LK_CANRECURSE);
73
74   Destroying it is trivial,
75         mtx_destroy(&my_mtx);
76   becomes
77         lockuninit(&my_lock);
78
79   You use the same function for locking and unlocking a lockmgr lock,
80   so exchange
81         mtx_lock(&my_mtx);
82   with
83         lockmgr(&my_lock, LK_EXCLUSIVE);
84   and
85         mtx_unlock(&my_mtx);
86   with
87         lockmgr(&my_lock, LK_RELEASE);
88
89   For testing the lock status, one would use
90         lockstatus(&my_lock, curthread);
91   in place of
92         mtx_owned(&my_mtx);
93
94   An
95         mtx_trylock(&my_mtx);
96   call is replaced with
97         lockmgr(&my_lock, LK_EXCLUSIVE|LK_NOWAIT);
98
99   As for mtx_assert() calls, translate them like this:
100
101         mtx_assert(&my_mtx, MA_OWNED) -> KKASSERT(lockstatus(&my_lock, curthread) != 0)
102         mtx_assert(&my_mtx, MA_NOTOWNED) -> KKASSERT(lockstatus(&my_lock, curthread) == 0)
103
104   In DragonFly, lockstatus() does not return information about whether there have been
105   recursive lock acquisitions, so there is no generic way to emulate the
106
107         mtx_assert(&my_mtx, MA_OWNED|MA_RECURSED);
108         mtx_assert(&my_mtx, MA_OWNED|MA_NOTRECURSED);
109
110   calls.
111         
112 * UMA conversion - generally speaking UMA should be converted to a standard
113   kmalloc.
114
115   Note however that in FreeBSD M_NOWAIT is often used in cases where, in fact,
116   the kmalloc cannot fail without blowing something up or causing a fatal
117   (and very unexpected) I/O error.  M_INTWAIT should be used for these cases.
118
119 * CDEVSW conversion - see other devices.  Generally speaking a major number
120   is needed and a function map needs to be specified more explicitly.
121
122   Most calls passing struct cdev pointers are dev_t's in DragonFly.
123
124   All device vectors in DragonFly pass a dev_<name>_args structure pointer
125   instead of explicit arguments.
126
127   Strategy calls - we pass BIO's and a lot of BUF fields are in the BIO
128   in FreeBSD, but left in the BUF in DragonFly.  FreeBSD for some reason
129   names its struct bio pointers 'bp', its a good idea to rename them to 'bio'
130   to avoid confusion and have a struct buf *bp = bio->bio_buf; pointer to
131   access the buf.
132
133 * MSLEEP/TSLEEP conversion.  The DragonFly msleep/tsleep do not have 'PRI'
134   priorities.  0 should be used.
135
136 * BUS_* FUNCTIONS
137
138   bus_setup_intr() - replace INTR_TYPE_* flags with 0.  There is an extra
139   argument for an interrupt interlock using the sys/serializer.h interface.
140   This can either be left NULL or you can convert the spinlock(s) for
141   the driver into serializer locks and integrate the interrupt service
142   routine with a serializer.
143
144 * CAM CODE - cam_simq* code refcounts, so shared device queues (raid and
145   multi-channel devices) are not freed before all references have gone
146   away.