⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 notes.txt

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 TXT
字号:
The following is a sort of theory of operation for aux/vga and thekernel vga drivers.--- aux/vga and basic kernel driversAux/vga consists of a number of modules each of which conforms to aninterface called a Ctlr.  The Ctlr provides functions snarf, options,init, load, and dump, which are explained in more detail below.  Videocards are internally represented as just a collection of Ctlrs.  Whenwe want to run one of the functions (snarf, etc.)  on the whole card,we run it on each Ctlr piece in turn.In the beginning of aux/vga, it was common for video cards to mix andmatch different VGA controller chips, RAMDACs, clock generators, andsometimes even hardware cursors.  The original use for vgadb was toprovide a recipe for how to deal with each card.  The ordering in thectlr sections was followed during initialization, so that if you said	ctlr		0xC0076="Tseng Laboratories, Inc. 03/04/94 V8.00N"		link=vga		clock=ics2494a-324		ctlr=et4000-w32p		ramdac=stg1602-135when aux/vga wanted to run, say, snarf on this card it would call thesnarf routines for the vga, ics2494a, et4000, and stg1602 Ctlrs, inthat order.  The special Ctlrs vga and ibm8514 take care of thegeneric VGA register set and the extensions to that register setintroduced by the IBM 8514 chip.  Pretty much all graphics cards thesedays still use the VGA register set with some extensions.  The onlyexceptions currently in vgadb are the Ticket to Ride IV and theNeomagic (both LCD cards).  The S3 line of chips tends to have the IBM8514 extensions.This "mix and match" diversity has settled down a bit, with one chipnow usually handling everything.  As a result, vgadb entries havebecome a bit more formulaic, usually listing only the vga link, acontroller, and a hardware cursor.  For example:	ctlr		0xC0039="CL-GD540"		link=vga		ctlr=clgd542x		hwgc=clgd542xhwgcOn to the controller functions themselves.  The functions mentionedearlier are supposed to do the following.void snarf(Vga *vga, Ctlr *ctlr)	Read the ctlr's registers into memory, storing them	either in the vga structure (if there is an appropriate	place) or into a privately allocated structure, a pointer	to which can be stored in vga->private [sic]. 	[The use of vga->private rather than ctlr->private betrays	the fact that private data has only been added after we got	down to having cards with basically a single controller.]void options(Vga *vga, Ctlr *ctlr)	This step prepares to edit the in-memory copy of the	registers to implement the mode given in vga->mode.	It's really the first half of init, and is often empty.	Basically, something goes here if you need to influence	one of the other init routines and can't depend on being	called before it.  For example, the virge Ctlr rounds	the pixel line width up to a multiple of 16 in its options routine.	This is necessary because the vga Ctlr uses the pixel line	width.  If we set it in virge.init, vga.init would already	have used the wrong value.void init(Vga *vga, Ctlr *ctlr)	Edit the in-memory copy of the registers to implement	the mode given in vga->mode.void load(Vga *vga, Ctlr *ctlr)	Write all the ctlr's registers, using the in-memory values.	This is the function actually used to switch modes.void dump(Vga *vga, Ctlr *ctlr)	Print (to the Biobuf stdout) a description of all the	in-memory controller state.  This includes the in-memory	copy of the registers but often includes other calculated	state like the intended clock frequencies, etc.Now we have enough framework to explain what aux/vga does.  It'seasiest to present it as a commented recipe.1.  We sniff around in the BIOS memory looking for a match toany of the strings given in vgadb.  (In the future, we intend also touse the PCI configuration registers to identify cards.)2.  Having identified the card and thus made the list of controllerstructures, we snarf the registers and, if the -p flag wasgiven, dump them.3.  If the -i or -l flag is given, aux/vga then locates the desiredmode in the vgadb and copies it into the vga structure.  It then doesany automatic frequency calculations if they need doing.  (See thediscussion of defaultclock in vgadb(6).)For a good introduction to video modes, read Eric Raymond's XFree86Video Timings HOWTO, which, although marked as obsolete for XFree86,is still a good introduction to what's going on between the video cardand the monitor.http://www.linuxdoc.org/HOWTO/XFree86-Video-Timings-HOWTO/4.  Having copied the vgadb mode parameters into the vga structure,aux/vga calls the options and then the init routines to twiddle thein-memory registers appropriately.5.  Now we are almost ready to switch video modes.  We dump theregisters to stdout if we're being verbose.6.  We tell the kernel (via the "type" vga ctl message) what sort ofvideo card to look for.  Specifically, the kernel locates the namedkernel vga driver and runs its enable function.7.  If we're using a frame buffer in direct-mapped linear mode (seethe section below), we express this intent with a "linear" vga ctlmessage.  In response, the kernel calls the vga driver's linearfunction.  This should map the video memory into the kernel's addressspace.  Conventionally, it also creates a named memory segment for usewith segattach so that uesr-level programs can get at the videomemory.  If there is a separate memory-mapped i/o space, it too ismapped and named.  These segments are only used for debugging,specifically for debugging the hardware acceleration routines fromuser space before putting them into the kernel.8.  We tell the kernel the layout of video memory in a "size" ctlmessage.  The arguments are the screen image resolution and the pixelchannel format string.9.  Everything is set; we disable the video card, call the loads toactally set the real registers, and reenable the card.At this point there should be a reasonable picture on the screen.  Itwill be of random memory contents and thus could be mostly garbage,but there should be a distinct image on the screen rather than, say,funny changing patterns due to having used an incorrect syncfrequency.10.  We write "drawinit" into #v/vgactl, which will initialize thescreen and make console output from now on appear on the graphicsscreen instead of being written to the CGA text video memory (as hasbeen happening).  This calls the kernel driver's drawinit function,whose only job is to initialize hardware accelerated fills and scrollsand hardware blanking if desired.11.  We write "hwgc <hwgcname>" into #v/vgactl, which calls the enablefunction on the named kernel hwgc driver.  (Plan 9 does not yet supportsoftware graphics cursors.)12.  We set the actual screen size with an "actualsize" ctl message.The virtual screen size (which was used in the "size" message in step8) controls how the video memory is laid out; the actual screen sizeis how much fits on your monitor at a time.  Virtual screen size issometimes larger than actual screen size, either to implement panning(which is really confusing and not recommended) or to round pixellines up to some boundary, as is done on the ViRGE and Matrox cards.The only reason the kernel needs to know the actual screen size is tomake sure the mouse cursor stays on the actual screen.13.  If we're being verbose, we dump the vga state again.--- hardware acceleration and blankingHardware drawing acceleration is accomplished by calling thekernel-driver-provided fill and scroll routines rather thandoing the memory operations ourselves.  For >8-bit pixel depths,hardware acceleration is noticeably needed.  For typical Plan 9applications, accelerating fill and scroll has been fast enough that we haven'tworried about doing anything else.  The kernel driver's drawinit function should sniff the cardand decide whether it can use accelerated fill and scroll functions.If so, it fills in the scr->fill and scr->scroll function pointerswith functions that implement the following:int fill(VGAscr *scr, Rectangle r, ulong val);	Set every pixel in the given rectangle to val.	Val is a bit pattern already formatted for the screen's	pixel format (rather than being an RGBA quadruple).	Do not return until the operation has completed	(meaning video memory has been updated).	Usually this means a busy wait looping for a bit	in some status register.  Although slighty inefficient,	the net effect is still much faster than doing the work 	ourselves.  It's a good idea to break out of the busy	loop after a large number of iterations, so that	if the driver or the card gets confused we don't	lock up the system waiting for the bit.  Look at	any of the accelerated drivers for the conventional	method.	int scroll(VGAscr *scr, Rectangle r, Rectangle sr);	Set the pixels in rectangle r with the pixels in sr.	r and sr are allowed to overlap, and the correct	thing must be done, just like memmove.	Like fill, scroll must not return until the operation	has completed.Russ Cox <rsc@plan9.bell-labs.com> has a user-level scaffoldfor testing fill and scroll routines before putting them intothe kernel.  You can mail him for them.Finally, drawinit can set scr->blank to a hardware blankingfunction.  On 8-bit displays we can set the colormap to allblack to get a sort of blanking, but for true-color displayswe need help from the hardware.int blank(VGAscr *vga, int isblank);	If isblank is set, blank the screen.  Otherwise, restore it.	Implementing this function on CRT-based cards is known to	mess up the registers coming out of the blank.	We've had better luck with LCD-based cards although	still not great luck.  But there it is.--- linear mode and soft screensIn the bad old days, the entire address space was only 1MB, but videomemory (640x480x1) was only 37.5kB, so everything worked out.  It gotits own 64kB segment and everyone was happy.  When screens got deeperand then bigger, the initial solution was to use the 64kB segment as awindow onto a particular part of video memory.  The offset of thewindow was controlled by setting a register on the card.  This worksokay but is a royal pain, especially if you're trying to copy from onearea of the screen to another and they don't fit in the same window.When we are forced to cope with cards that require accessing memorythrough the 64kB window, we allocate our own copy of the screen (aso-called soft screen) in normal RAM, make changes there, and thenflush the changed portions of memory to video RAM through the window.To do this, we call the kernel driver-provided page routine:int pageset(VGAscr *scr, int page);	Set the base offset of the video window to point	page*64kB into video memory.With the advent of 32-bit address spaces, we can map all of videomemory and avoid the soft screen.  We call this running the cardin linear mode, because the whole video memory is mapped linearlyinto our address space.  Aux/vga is in charge of decidingwhether to do this.  (In turn, aux/vga more or less respectsvgadb, which controls it by having or not having "linear=1" inthe controller entry.)  If not, aux/vga doesn't do anything special,and we use a soft screen.  If so, aux/vga writes "linear" andan address space size into vgactl in step #7 above.  In responsethe kernel calls the kernel driver's linear function, whosejob was described in step #7.Most drivers only implement one or the other interface: if you'vegot linear mode, you might as well use it and ignore the pagingcapabilties of the card.  Paging is typically implemented onlywhen necessary.--- from hereIf you want to write a VGA driver, it's fairly essential that you getdocumentation for the video chipset.  In a pinch, you might be able toget by with the XFree86 driver for the chipset instead.  (The NVidiadriver was written this way.)  Another alternative is to usedocumentation for a similar but earlier chipset and then tweakregisters until you figure out what is different.  (The SuperSavageparts of the virge driver got written this way, starting with theSavage4 parts, which in turn were written by referring to the Savage4documentation and the Virge parts.)Even if you do get documentation, the XFree86 driver is good tohave to double check.  Sometimes the documentation is incomplete,misleading, or just plain wrong, whereas the XFree86 drivers, complicated beasts though they are, are known to work most of the time.Another useful method for making sure you understand what is going onis dumping the card's registers under another system like XFree86 orMicrosoft Windows.  The Plan 9 updates page contains an ANSI/POSIXport of aux/vga that is useful only for dumping registers on varioussystems.  It has been used under Linux, FreeBSD, and Windows 95/98.It's not clear what to do on systems like Windows NT or Windows 2000that both have reasonable memory protection and are hardwareprogrammer-unfriendly.If you're going to write a driver, it's much easier with a realPlan 9 network or at least with a do-everything cpu/auth/file serverterminal, so that you can have an editor and compiler going on ausable machine while you continually frotz and reboot the machinewith the newfangled video card.  Booting this latter machine fromthe network rather than its own disk makes life easier for you(you don't have to explicitly copy aux/vga from the compiling machine tothe testing machine) and doesn't wreak havoc on the testing machine'slocal kfs.It's nice sometimes to have a command-line utility to pokeat the vga registers you care about.  We have one that perhapswe can clean up and make available.  Otherwise, it's not hardto roll your own.The first step in writing an aux/vga driver is to write thesnarf and dump routines for the controller.  Then you canrun aux/vga -p and see whether the values you are gettingmatch what you expect from the documentation you have.A good first resolution to try to get working is 640x480x8,as it can use one of the standard clock modes rather thanrequire excessive clock fiddling./sys/src/cmd/aux/vga/template.c is a template for a newvga controller driver.  There is no kernel template but any of the current drivers is a decent template./sys/src/9/pc/vga3dfx.c is the smallest one that supportslinear addressing mode.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -