16eef04ebSFrançois Tigeot PORTING FREEBSD DRIVERS TO DRAGONFLY 26eef04ebSFrançois Tigeot 36eef04ebSFrançois Tigeot* Copy the driver code to the appropriate DragonFly directory. For example, 46eef04ebSFrançois Tigeot a disk driver /usr/src/sys/dev/blah in FreeBSD would likely be 56eef04ebSFrançois Tigeot /usr/src/sys/dev/disk/blah in DragonFly. 66eef04ebSFrançois Tigeot 7efb850f9SSascha Wildner* Keep all the SVN IDs in the files as a future reference point. dports' SVN 845fa0bf8SSascha Wildner will do that by default. When using the FreeBSD git repo, please note the 9efb850f9SSascha Wildner files' IDs manually, either in the files themselves or in the commit message. 10efb850f9SSascha Wildner The general idea is that it must not get lost. 116eef04ebSFrançois Tigeot 126eef04ebSFrançois Tigeot* Driver local #include's probably use a <dev/blah/blah.h> path. These 136eef04ebSFrançois Tigeot need to be changed to "blah.h". '.' is not included in the #include 146eef04ebSFrançois Tigeot path in FreeBSD builds, but it is in DragonFly builds. 156eef04ebSFrançois Tigeot 166eef04ebSFrançois Tigeot* Other #include's may reference things in <dev/...> which in DragonFly 176eef04ebSFrançois Tigeot reside in <bus/...>. In particular, dev/pccard becomes bus/pccard. 186eef04ebSFrançois Tigeot Note that defines in FreeBSD's pccard_cis.h reside in DragonFly's 196eef04ebSFrançois Tigeot pccardreg.h . 206eef04ebSFrançois Tigeot 216eef04ebSFrançois Tigeot* The following kernel functions have been renamed in DragonFly: 226eef04ebSFrançois Tigeot 236eef04ebSFrançois Tigeot malloc(), free() etc. -> kmalloc(), kfree() etc. 246eef04ebSFrançois Tigeot printf() etc. -> kprintf() etc. 256eef04ebSFrançois Tigeot psignal() -> ksignal() 266eef04ebSFrançois Tigeot random() -> krandom() 276eef04ebSFrançois Tigeot 286eef04ebSFrançois Tigeot* MUTEX conversion - mutexes are generally replaced by spinlocks. However, 296eef04ebSFrançois Tigeot DragonFly spinlocks are more restrictive than FreeBSD mutexes so a 306eef04ebSFrançois Tigeot direct replacement is not necessarily appropriate in all cases. A lockmgr 316eef04ebSFrançois Tigeot lock should be used when a direct replacement is not appropriate. 326eef04ebSFrançois Tigeot In particular, DragonFly does not allow recursive exclusive spinlocks 336eef04ebSFrançois Tigeot and does not allow multiple exclusive spinlocks to be held by any given 346eef04ebSFrançois Tigeot thread. 356eef04ebSFrançois Tigeot 366eef04ebSFrançois Tigeot Instances of <sys/mutex.h> should be replaced with <sys/spinlock.h>. 376eef04ebSFrançois Tigeot 386eef04ebSFrançois Tigeot When replacing mutexes with spinlocks it is a good idea to rename 396eef04ebSFrançois Tigeot the structural field (typically 'mtx') to something else (typically 'spin'). 406eef04ebSFrançois Tigeot 416eef04ebSFrançois Tigeot The &Giant mutex is typically converted to get_mplock() and rel_mplock(). 426eef04ebSFrançois Tigeot However, there are places where FreeBSD unlocks giant around some code and 436eef04ebSFrançois Tigeot then relocks giant... those should simply be removed. 446eef04ebSFrançois Tigeot 456eef04ebSFrançois Tigeot FreeBSD has weird callout + mutex functions. DragonFly does not integrate 466eef04ebSFrançois Tigeot the two. Instead, the driver in DragonFly must obtain the spinlocks 476eef04ebSFrançois Tigeot in question in the callback routine. 486eef04ebSFrançois Tigeot 496eef04ebSFrançois Tigeot As a rule of thumb, MTX_DEF mutexes should be replaced with exclusive, 506eef04ebSFrançois Tigeot recursive lockmgr locks. 516eef04ebSFrançois Tigeot 526eef04ebSFrançois Tigeot So, suppose the original code is using 536eef04ebSFrançois Tigeot struct mtx my_mtx; 546eef04ebSFrançois Tigeot you'd normally rename it to 556eef04ebSFrançois Tigeot struct lock my_lock; 566eef04ebSFrançois Tigeot 576eef04ebSFrançois Tigeot and change the initialization from something like 586eef04ebSFrançois Tigeot mtx_init(&my_mtx, "mymtx", "whatever", MTX_DEF); 596eef04ebSFrançois Tigeot to 606eef04ebSFrançois Tigeot lockinit(&my_lock, "mylock", 0, LK_CANRECURSE); 616eef04ebSFrançois Tigeot 626eef04ebSFrançois Tigeot Destroying it is trivial, 636eef04ebSFrançois Tigeot mtx_destroy(&my_mtx); 646eef04ebSFrançois Tigeot becomes 656eef04ebSFrançois Tigeot lockuninit(&my_lock); 666eef04ebSFrançois Tigeot 676eef04ebSFrançois Tigeot You use the same function for locking and unlocking a lockmgr lock, 686eef04ebSFrançois Tigeot so exchange 696eef04ebSFrançois Tigeot mtx_lock(&my_mtx); 706eef04ebSFrançois Tigeot with 716eef04ebSFrançois Tigeot lockmgr(&my_lock, LK_EXCLUSIVE); 726eef04ebSFrançois Tigeot and 736eef04ebSFrançois Tigeot mtx_unlock(&my_mtx); 746eef04ebSFrançois Tigeot with 756eef04ebSFrançois Tigeot lockmgr(&my_lock, LK_RELEASE); 766eef04ebSFrançois Tigeot 776eef04ebSFrançois Tigeot For testing the lock status, one would use 786eef04ebSFrançois Tigeot lockstatus(&my_lock, curthread); 796eef04ebSFrançois Tigeot in place of 806eef04ebSFrançois Tigeot mtx_owned(&my_mtx); 816eef04ebSFrançois Tigeot 826eef04ebSFrançois Tigeot An 836eef04ebSFrançois Tigeot mtx_trylock(&my_mtx); 846eef04ebSFrançois Tigeot call is replaced with 85*a9ea4065SSascha Wildner lockmgr_try(&my_lock, LK_EXCLUSIVE); 866eef04ebSFrançois Tigeot 876eef04ebSFrançois Tigeot As for mtx_assert() calls, translate them like this: 886eef04ebSFrançois Tigeot 896eef04ebSFrançois Tigeot mtx_assert(&my_mtx, MA_OWNED) -> KKASSERT(lockstatus(&my_lock, curthread) != 0) 906eef04ebSFrançois Tigeot mtx_assert(&my_mtx, MA_NOTOWNED) -> KKASSERT(lockstatus(&my_lock, curthread) == 0) 916eef04ebSFrançois Tigeot 926eef04ebSFrançois Tigeot In DragonFly, lockstatus() does not return information about whether there have been 936eef04ebSFrançois Tigeot recursive lock acquisitions, so there is no generic way to emulate the 946eef04ebSFrançois Tigeot 956eef04ebSFrançois Tigeot mtx_assert(&my_mtx, MA_OWNED|MA_RECURSED); 966eef04ebSFrançois Tigeot mtx_assert(&my_mtx, MA_OWNED|MA_NOTRECURSED); 976eef04ebSFrançois Tigeot 986eef04ebSFrançois Tigeot calls. 996eef04ebSFrançois Tigeot 1004b3fb495SFrançois Tigeot* rwlock conversion: Use lockmgr locks 1014b3fb495SFrançois Tigeot 1026eef04ebSFrançois Tigeot* UMA conversion - generally speaking UMA should be converted to a standard 1036eef04ebSFrançois Tigeot kmalloc. 1046eef04ebSFrançois Tigeot 1056eef04ebSFrançois Tigeot Note however that in FreeBSD M_NOWAIT is often used in cases where, in fact, 1066eef04ebSFrançois Tigeot the kmalloc cannot fail without blowing something up or causing a fatal 1076eef04ebSFrançois Tigeot (and very unexpected) I/O error. M_INTWAIT should be used for these cases. 1086eef04ebSFrançois Tigeot 1096eef04ebSFrançois Tigeot* CDEVSW conversion - see other devices. Generally speaking a major number 1106eef04ebSFrançois Tigeot is needed and a function map needs to be specified more explicitly. 1116eef04ebSFrançois Tigeot 1126eef04ebSFrançois Tigeot Most calls passing struct cdev pointers are dev_t's in DragonFly. 1136eef04ebSFrançois Tigeot 1146eef04ebSFrançois Tigeot All device vectors in DragonFly pass a dev_<name>_args structure pointer 1156eef04ebSFrançois Tigeot instead of explicit arguments. 1166eef04ebSFrançois Tigeot 1176eef04ebSFrançois Tigeot Strategy calls - we pass BIO's and a lot of BUF fields are in the BIO 1186eef04ebSFrançois Tigeot in FreeBSD, but left in the BUF in DragonFly. FreeBSD for some reason 1196eef04ebSFrançois Tigeot names its struct bio pointers 'bp', its a good idea to rename them to 'bio' 1206eef04ebSFrançois Tigeot to avoid confusion and have a struct buf *bp = bio->bio_buf; pointer to 1216eef04ebSFrançois Tigeot access the buf. 1226eef04ebSFrançois Tigeot 1236eef04ebSFrançois Tigeot* MSLEEP/TSLEEP conversion. The DragonFly msleep/tsleep do not have 'PRI' 1246eef04ebSFrançois Tigeot priorities. 0 should be used. 1256eef04ebSFrançois Tigeot 1266eef04ebSFrançois Tigeot* BUS_* FUNCTIONS 1276eef04ebSFrançois Tigeot 1286eef04ebSFrançois Tigeot bus_setup_intr() - replace INTR_TYPE_* flags with 0. There is an extra 1296eef04ebSFrançois Tigeot argument for an interrupt interlock using the sys/serializer.h interface. 1306eef04ebSFrançois Tigeot This can either be left NULL or you can convert the spinlock(s) for 1316eef04ebSFrançois Tigeot the driver into serializer locks and integrate the interrupt service 1326eef04ebSFrançois Tigeot routine with a serializer. 1336eef04ebSFrançois Tigeot 1346eef04ebSFrançois Tigeot* CAM CODE - cam_simq* code refcounts, so shared device queues (raid and 1356eef04ebSFrançois Tigeot multi-channel devices) are not freed before all references have gone 1366eef04ebSFrançois Tigeot away. 137317f6748SFrançois Tigeot 138de612e47SFrançois Tigeot* UNRHDR functions - DragonFly uses a more generic idr(9) subsystem 139de612e47SFrançois Tigeot compatible with the Linux API of the same name 140de612e47SFrançois Tigeot 141de612e47SFrançois Tigeot This LWN article describes it in details: http://lwn.net/Articles/103209/ 142de612e47SFrançois Tigeot 143de612e47SFrançois Tigeot A typical conversion looks like this: 144de612e47SFrançois Tigeot 145de612e47SFrançois Tigeot #include <sys/idr.h> 146de612e47SFrançois Tigeot 147de612e47SFrançois Tigeot free_unr() has to be replaced by idr_remove() 148de612e47SFrançois Tigeot 149de612e47SFrançois Tigeot alloc_unr() has to be replaced by a code sequence using idr_pre_get and 150de612e47SFrançois Tigeot idr_get_new such as this one: 151de612e47SFrançois Tigeot 152de612e47SFrançois Tigeot retry: 153de612e47SFrançois Tigeot if (idr_pre_get(xxx) ==0) { 154de612e47SFrançois Tigeot kprintf("Memory allocation error\n"); 155de612e47SFrançois Tigeot return error; 156de612e47SFrançois Tigeot } 157de612e47SFrançois Tigeot spin_lock(xxx); 158de612e47SFrançois Tigeot ret = idr_get_new(xxx); 159de612e47SFrançois Tigeot spin_unlock(xxx); 160de612e47SFrançois Tigeot if (ret == EAGAIN) 161de612e47SFrançois Tigeot goto retry; 162de612e47SFrançois Tigeot 1634dd401bdSFrançois Tigeot* MPASS macro - Replace it with KKASSERT 1642764c241SAntonio Huete Jimenez 165cf396422SFrançois Tigeot 166cf396422SFrançois Tigeot* PROC_LOCK / PROC_UNLOCK: to be determined on a case-by-case basis 167cf396422SFrançois Tigeot 168cf396422SFrançois Tigeot Some of the time these macros can be removed entirely 169cf396422SFrançois Tigeot 170cf396422SFrançois Tigeot In some cases, some locking must be done; lwkt_gettoken(&proc_token) 171cf396422SFrançois Tigeot and the corresponding lwkt_reltoken() call should be good replacements 172cf396422SFrançois Tigeot 173cf396422SFrançois Tigeot It is not a good idea to blindly implement these macros globally, some 174cf396422SFrançois Tigeot particular proc subsystem locking semantics differ enough between FreeBSD 175cf396422SFrançois Tigeot and DragonFly that this would cause problems 176cf396422SFrançois Tigeot 177d00c6212Szrj* In DragonFly 5.1 format specifier %b was replaced by args safe "%pb%i" version 178d00c6212Szrj that only needs argument swapping. Replacement functions where not added. 179d00c6212Szrj 180d00c6212Szrj kvcprintf("reg=%pb%i\n", "\10\2BITTWO\1BITONE\n", 3); 181d00c6212Szrj 182d00c6212Szrj* In DragonFly 5.1 format specifier %r was removed from kprintf. As a 183d00c6212Szrj replacement function makedev_unit_b32() was added. 184d00c6212Szrj 185d00c6212Szrj - Unit suffix encoded as base32 for make_dev() device creation: 186d00c6212Szrj 187d00c6212Szrj char tbuf[MAKEDEV_MINNBUF]; 188d00c6212Szrj 189d00c6212Szrj kbd->kb_dev = make_dev(&kbd_ops, kbd->kb_index, 190d00c6212Szrj UID_ROOT, GID_WHEEL, 0600, "kbd%s", 191d00c6212Szrj makedev_unit_b32(tbuf, kbd->kb_index)); 192d00c6212Szrj 193d00c6212Szrj - For single character case the hex2ascii() can be used to avoid buffers: 194d00c6212Szrj 195d00c6212Szrj kprintf("%c\n", hex2ascii(n % base)); 196cf396422SFrançois Tigeot 1972764c241SAntonio Huete Jimenez* In DragonFly 3.3 format specifier %D was removed from kprintf. As a 1982764c241SAntonio Huete Jimenez replacement functions kether_ntoa() and hexncpy() were added. 1992764c241SAntonio Huete Jimenez 2002764c241SAntonio Huete Jimenez - Ethernet address (MAC) to its hexadecimal form: 2012764c241SAntonio Huete Jimenez 2022764c241SAntonio Huete Jimenez char ethstr[ETHER_ADDRSTRLEN + 1]; 2032764c241SAntonio Huete Jimenez u_char hwaddr[6]; 2042764c241SAntonio Huete Jimenez 2052764c241SAntonio Huete Jimenez kprintf("MAC address %s\n", kether_ntoa(hwaddr, ethstr) 2062764c241SAntonio Huete Jimenez 2072764c241SAntonio Huete Jimenez - Generic conversion (block of bytes to hexadecimal form): 2082764c241SAntonio Huete Jimenez 2092764c241SAntonio Huete Jimenez char hexstr[18]; 2102764c241SAntonio Huete Jimenez u_char mydata[6] = {1, 2, 3, 4, 5 ,6}; 2112764c241SAntonio Huete Jimenez 2122764c241SAntonio Huete Jimenez /* 2132764c241SAntonio Huete Jimenez * Below statement would print: 2142764c241SAntonio Huete Jimenez * 2152764c241SAntonio Huete Jimenez * 01-02-03-04-05-06 2162764c241SAntonio Huete Jimenez */ 2172764c241SAntonio Huete Jimenez kprintf("%s\n", hexncpy(mydata, 6, hexstr, HEX_NCPYLEN(6), "-")); 2184b3fb495SFrançois Tigeot 2194b3fb495SFrançois Tigeot* TAILQ_XXX_SAFE 2204b3fb495SFrançois Tigeot 2214b3fb495SFrançois Tigeot Use TAILQ_XXX_MUTABLE; the macros have the same effect, only the name is 2224b3fb495SFrançois Tigeot different 2234b3fb495SFrançois Tigeot 2244b3fb495SFrançois Tigeot* kern_yield() 2254b3fb495SFrançois Tigeot 2264b3fb495SFrançois Tigeot Replace by lwkt_yield() 2274b3fb495SFrançois Tigeot 2284b3fb495SFrançois Tigeot* vm_page_lock() and vm_page_unlock() 2294b3fb495SFrançois Tigeot 2304b3fb495SFrançois Tigeot Not needed on DragonFly, remove these calls 2314b3fb495SFrançois Tigeot 2324b3fb495SFrançois Tigeot* vm_pager_get_pages() 2334b3fb495SFrançois Tigeot 2344b3fb495SFrançois Tigeot Removed, use vm_pager_get_page() instead 2354b3fb495SFrançois Tigeot 2364b3fb495SFrançois Tigeot* VPO_BUSY 2374b3fb495SFrançois Tigeot 2384b3fb495SFrançois Tigeot Replace by PG_BUSY 2394b3fb495SFrançois Tigeot 2404b3fb495SFrançois Tigeot* kern_psignal() 2414b3fb495SFrançois Tigeot 2424b3fb495SFrançois Tigeot Replace by ksignal() 243