Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site harvard.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!think!harvard!nick From: nick@harvard.UUCP (Nick Vasilatos) Newsgroups: net.unix-wizards Subject: Re: Device Drivers in Xenix Message-ID: <814@harvard.UUCP> Date: Tue, 1-Apr-86 02:40:16 EST Article-I.D.: harvard.814 Posted: Tue Apr 1 02:40:16 1986 Date-Received: Sat, 5-Apr-86 01:21:53 EST References: <709@mprvaxa.UUCP> Organization: Aiken Comp Lab, Harvard Lines: 70 > I am trying to write a device driver for SCO's Xenix SYSTEM V release 2 Assorted lore -- A paddr_t is a (long) physical address (intended for real, live, on the bus addresses), see . The kernel, data first, is (or was, last I looked) loaded at 0x4000, so add 0x4000 to a kernel logical address to get a physical address. Far pointers are 32 bit pointers, the high word of which is an offset into either a particular local, or the system global descriptor table (LDT or GDT as it were; physical addresses are not directly meaningful to the 286 -- it operates on 16 bit address offsets interpreted relative to base addresses determined from the contents of it's various segment registers vis a vis these tables). To set up a far pointer for accessing physical addresses in a device driver: Call (unsigned) dscralloc() to obtain a gdt descriptor for exclusive use by your driver (a compile time configurable number of which are reserved for such use). It returns a ``selector'' which is the (aforementioned) offset of the descriptor in the gdt. Fill in the elements (address, limit (segment size - 1) and protection) of the descriptor. Use: mmudescr((unsigned) selector, (paddr_t) address, (unsigned) limit, (char) (access = DSA_DATA, from )); The limit should be the size of the object you are trying access. The hardware will favour you with a general protection trap if you exceed that limit (ie. miss) if you set it correctly. Make a far pointer out of the selector and a zero offset with a macro provided in : char far *dp = sotofar(selector,0); In as much as the 286 has a ruthlessly efficient string move, you probably don't want to code loops around far pointer assignments. For such as that use: copyseg((paddr_t) source, (paddr_t) dest, (unsigned) cnt); They are otherwise the right way to poke around the address space. If the device you are trying to drive's privies are memory mapped, you are in business. If they are I/O mapped (attached to the 286's seperate, 64k i/o bus) you are stuck with in and out instructions (accessed via in() and out() calls and i/o space relative 16 bit offsets). The drill in general is to create a C structure describing your device registers, data buffers, or what have you that you're trying to access and use it's size to determine the segment limit and reference it to determine offsets, however you must apply them. The initialization handler of your driver is the apropo place to undertake descriptor allocation and setup. Physio disallows i/o into text or unallocated user memory (reasonable) -- a buffer that is mapped into a single data segment must be referenced by base and count in u. It also disallows odd addresses and counts. It also insists on even block multiples unless the BTAPE flag in the buffer header you're passing it is set.