1706f2543Smrg
2706f2543Smrg                 INT10  X86 Real Mode executor
3706f2543Smrg                 =============================
4706f2543Smrg
5706f2543Smrg		         PRELIMINARY
6706f2543Smrg
7706f2543SmrgINT10 is  a XFree86  module for soft-booting  and executing  real mode
8706f2543Smrgint10 BIOS calls. The BIOS call code is largely untested, yet.
9706f2543Smrg
10706f2543Smrg1. Usage
11706f2543Smrg========
12706f2543Smrg
13706f2543SmrgTo   use   the   int10   module   in  a   driver   the   header   file
14706f2543Smrgxfree86/os-support/int10/xf86int10.h must be included.
15706f2543Smrg
16706f2543Smrg a. Initialization
17706f2543Smrg -----------------
18706f2543Smrg
19706f2543SmrgThe int10-executer gets initialized by calling:
20706f2543Smrg
21706f2543Smrg   xf86Int10InfoPtr xf86InitInt10(int entityIndex);
22706f2543Smrg
23706f2543SmrgThe  function  will soft-boot  any  non-primary  device  and return  a
24706f2543Smrgpointer  to a  xf86Int10InfoRec on  success. If  anything fails  or if
25706f2543Smrgint10 execution  is disabled by an  option in the  device section NULL
26706f2543Smrgwill  be returned.   The driver  should store  this pointer  for later
27706f2543Smrgcalls to other int10 module functions.
28706f2543Smrg
29706f2543Smrg b. Memory allocation
30706f2543Smrg --------------------
31706f2543Smrg
32706f2543SmrgTo allocate memory in the real mode execution environment
33706f2543Smrg    
34706f2543Smrg   void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off);
35706f2543Smrg
36706f2543Smrgcan  be called.  It  allocates num  consecutive  pagesize chunks.   It
37706f2543Smrgreturns the address of the allocated area. off is set to its offset in
38706f2543Smrgthe real mode memory space.
39706f2543Smrg
40706f2543Smrg  void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num);
41706f2543Smrg
42706f2543SmrgIs used to free num pages beginning at pbase.
43706f2543Smrg
44706f2543Smrg c. Doing int10 BIOS calls
45706f2543Smrg -------------------------
46706f2543Smrg
47706f2543SmrgThe BIOS call is executed by calling:
48706f2543Smrg   
49706f2543Smrg   void xf86ExecX86int10(xf86Int10InfoPtr pInt);
50706f2543Smrg
51706f2543SmrgThe number  of the interrupt (normally  10) and the  initial values of
52706f2543Smrgthe ax, bx, cx, dx, si, di  and es x86-CPU registers can be set in the
53706f2543Smrgxf86Int10InfoRec  passed to  the function.   On return  this structure
54706f2543Smrgcontains the  exit values  of the registers  listed above and  the CPU
55706f2543Smrgflag register.
56706f2543Smrg
57706f2543Smrg d. De-initializing
58706f2543Smrg -----------------
59706f2543Smrg
60706f2543SmrgIf no further int10 calls are required for a certain chipset
61706f2543Smrgthe driver should call:
62706f2543Smrg
63706f2543Smrg  void xf86FreeInt10(xf86Int10InfoPtr pInt);
64706f2543Smrg
65706f2543Smrgto free the memory allocated for real mode int10 calls.
66706f2543Smrg
67706f2543Smrg
68706f2543Smrg2. Porting issues
69706f2543Smrg=================
70706f2543Smrg
71706f2543SmrgThe int10 real mode executor is  designed to run on top of various x86
72706f2543SmrgCPU emulators as well as in vm86  mode of a real x86 CPU. If used with
73706f2543Smrga CPU  emulator the emulator and  CPU specific interfaces  can be held
74706f2543Smrgseparate thus  requiring minimal efforts  to port the int10  module to
75706f2543Smrgnew  platforms.   Currently  an  interface  to the  x86emu  real  mode
76706f2543Smrgemulator is  provided.  Since  details of setting  up and  running the
77706f2543Smrgvm86  mode   is  platform   dependent  both  the   platform  dependent
78706f2543Smrgenvironment and the emulation layer  have to be ported. Several helper
79706f2543Smrgfunctions are provided for that.
80706f2543Smrg
81706f2543SmrgA CPU emulator should meet certain requirements to be usable
82706f2543Smrgfor the INT10 executor:
83706f2543Smrg
84706f2543Smrg1. It must trap  calls to intXX instructions and  pass execution to an
85706f2543Smrg   external  function  which  is   allowed  to  modify  CPU  registers
86706f2543Smrg   including  the instruction  pointer  (IP) before  returning to  the
87706f2543Smrg   emulator for  continuing execution.  When the external  function is
88706f2543Smrg   called the  IP must point to  the instruction past  the intXX call.
89706f2543Smrg
90706f2543Smrg2. The  emulator should  use externally  provided functions  to handle
91706f2543Smrg   PIO.
92706f2543Smrg
93706f2543Smrg3.  The emulator  should be able to use  externally provided functions
94706f2543Smrg to access memory  from the real mode memory  environment.  Note, that
95706f2543Smrg the  vm86  mode  usually  requires  one hunk  of  consecutive  memory
96706f2543Smrg starting at address  0 in the process virtual  memory space.  Thus if
97706f2543Smrg this mode is to be used, the OS environment has to be able to provide
98706f2543Smrg that, ie. it must be able to remap the processes virtual memory space
99706f2543Smrg onto itself.  If the  emulator is able  to handle memory  access thru
100706f2543Smrg externally  provided functions the  real mode  process memory  can be
101706f2543Smrg located anywhere  in the processes  virtual memory. It does  not even
102706f2543Smrg have to be consecutive.
103706f2543Smrg
104706f2543Smrg4. The executor should terminate on encountering a 'hlt' instruction.
105706f2543Smrg
106706f2543Smrg
107706f2543SmrgFunctions to implement:
108706f2543Smrg
109706f2543SmrgTo simplify development  the code has been split  into a general setup
110706f2543Smrgpart and an emulator specific one. A generic setup code is provided in
111706f2543Smrggeneric.c.  It  should be  usable  with  any  emulator satisfying  the
112706f2543Smrgconditions mentioned  above. Therefore the following  section on int10
113706f2543Smrgsetup may be skipped when porting int10 to new emulator.
114706f2543Smrg
115706f2543SmrgIf the  vm86() is to be used  no memory access functions  can be used.
116706f2543SmrgTherefore the layout of the real mode memory image has to meet certain
117706f2543Smrgrequirements. Therefore  when porting to  other platforms a  new setup
118706f2543Smrgcode may  have to  be designed, too.  The following section  will give
119706f2543Smrgguidelines how  this may be  done. A sample implementation  using SysV
120706f2543SmrgIPC to  map the  appropriate real  mode memory image  to address  0 in
121706f2543Smrgvirtual  address  space  just  prior  to execution  may  be  found  in
122706f2543Smrgxfree86/os-support/linux/int10/linux.c.
123706f2543Smrg
124706f2543SmrgOn  non-PC like  platforms emulation  of certain  PC features  such as
125706f2543Smrginitialization of  BIOS int vectors, sys_BIOS constants  or PCI config
126706f2543Smrgmethod 1 can be turned on by defining _PC.
127706f2543Smrg
128706f2543SmrgI. Setup Code
129706f2543Smrg-------------
130706f2543Smrg
131706f2543SmrgThis sets  up the real mode  memory image, calls the  emulator to POST
132706f2543Smrgthe chipset if required and  maintains memory allocations in real mode
133706f2543Smrgaddress space.
134706f2543Smrg
135706f2543Smrg1. xf86Int10InfoPtr xf86InitInt10(int entityIndex);
136706f2543Smrg
137706f2543SmrgThis  function should  first find  the screen  assigned to  the entity
138706f2543Smrgcarrying entitiyIndex and then call
139706f2543Smrg
140706f2543Smrg       Bool int10skip(ScrnInfoPtr pScrn)
141706f2543Smrg
142706f2543Smrgto find out if the user  has requested not to initialize int10.  If so
143706f2543Smrgxf86InitInt10()  should  return  NULL. Otherwise  an  xf86Int10InfoRec
144706f2543Smrgshould be allocated.  This structure contains the following fields:
145706f2543Smrg
146706f2543Smrg    a. int entityIndex   - index of the entity whose BIOS is to be 
147706f2543Smrg                           executed.
148706f2543Smrg    b. int scrnIndex     - index of the screen assigned the entity.
149706f2543Smrg    c. pointer cpuRegs   - pointer to a emulator/vm86-mode private 
150706f2543Smrg                           structure.  May hold cpu register values 
151706f2543Smrg                           for the emulator.
152706f2543Smrg    d. CARD16 BIOSseg    - Video BIOS segment address.
153706f2543Smrg    e. pointer private   - pointer to a os specific data structure.
154706f2543Smrg    f. struct _int10Mem* - pointer to a structure to hold the memory
155706f2543Smrg                           access functions for use by an emulator.
156706f2543Smrg    g. int num           - number of the int to be called.
157706f2543Smrg    h. int ax..es,flags  - CPU register values to pass to int-call.
158706f2543Smrg
159706f2543SmrgThe Init  function should initialize  a-f. To initialize  the emulator
160706f2543Smrgspecific execute environment the function
161706f2543Smrg
162706f2543Smrg     Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt)
163706f2543Smrg
164706f2543Smrgshould be called. If this function returns FALSE any already allocated
165706f2543Smrgmemory should be freed and xf86Int10Init(0 should exit returning NULL.
166706f2543Smrg
167706f2543SmrgIf the  platform has  a PC  like system BIOS  it may  be copied  to or
168706f2543Smrgmapped into memory  locations SYS_BIOS to SYS_SIZE-1 of  the real mode
169706f2543Smrgmemory environment of this process. Otherwise the helper function: 
170706f2543Smrg
171706f2543Smrgint setup_system_bios(CARD32 base_addr); 
172706f2543Smrg
173706f2543Smrgmay be  called to set  up a rudimentary  system BIOS sufficient  to be
174706f2543Smrgused to  boot video BIOSes.   base_addr specifies the  virtual address
175706f2543Smrgcorresponding to SYS_BIOS in the  real mode environment.  If a PC-like
176706f2543Smrgint vector and BIOS data area is available it should be copied to 0 to
177706f2543SmrgLOW_PAGE_SIZE of the entities real mode environment.  In this case the
178706f2543Smrgvideo interrupt  related entries should  be reset for  all non-primary
179706f2543Smrgcards by calling:
180706f2543Smrg
181706f2543Smrgvoid reset_int_vect(xf86Int10InfoPtr pInt); To initialize the
182706f2543Smrg
183706f2543Smrgcorrect video BIOS  entry points the BIOS must  be warm-booted.  If no
184706f2543SmrgPC-like int vector is available one can be set up by calling 
185706f2543Smrg
186706f2543Smrgvoid setup_int_vect(xf86Int10InfoPtr pInt); 
187706f2543Smrg
188706f2543SmrgIn this  case the  video BIOS  has to be  warm-booted always.   If the
189706f2543Smrgvideo BIOS  for this entity has  been installed during boot  it may be
190706f2543Smrgmapped (or  copied) directly to the  correct address in  the real mode
191706f2543Smrgmemory environment.  Otherwise
192706f2543Smrg
193706f2543Smrgint mapPciRom(xf86Int10InfoPtr pInt, unsigned char * address); 
194706f2543Smrg
195706f2543Smrgshould  be called  to copy  the BIOS  image from  PCI  ROM.  'address'
196706f2543Smrgspecifies the address this image should be copied to. Sufficient space
197706f2543Smrgto  hold an entire  BIOS image  should be  allocated prior  to calling
198706f2543SmrgmapPciRom(). This function  will return the size of  the BIOS image in
199706f2543Smrgbytes  if  it   was  able  to  successfully  copy   the  image  and  0
200706f2543Smrgotherwise. To create a well defined point to exit the softbooter
201706f2543Smrg
202706f2543Smrgvoid set_return_trap(xf86Int10Ptr pInt); 
203706f2543Smrg
204706f2543Smrgmay be called.  It sets up a 'hlt' instruction  in the emulator memory
205706f2543Smrgjust above the BIOS variable area. Before entering real mode execution
206706f2543Smrgthis address will be pushed onto  the return stack.  If the BIOS needs
207706f2543Smrgto be  warm-booted this should be done  before leaving xf86InitInt10()
208706f2543Smrgby setting num in the xf86Int10InfoRec to 0xe6 and calling
209706f2543Smrg
210706f2543Smrgvoid xf86ExecX86int10(xf86Int10IfoPtr pInt); 
211706f2543Smrg
212706f2543SmrgThe  implementation of this  function will  be discussed  below.  This
213706f2543Smrgfunction  should be  wrapped  by calls  to void  LockLegacyVGA(screen,
214706f2543SmrglegacyVGAPtr vga); and void UnlockLegacyVGA(screen, legacyVGAPtr vga);
215706f2543SmrgThe struct  vga is  used to hold  the state  of the legacy  VGA access
216706f2543Smrgregisters  if  a legacy  VGA  device  exists.  xf86InitInt10()  should
217706f2543Smrgreturn a pointer to the xf86Int10InfoRec allocated.
218706f2543Smrg
219706f2543Smrg2. Bool MapCurrentInt10(xf86Int10InfoPtr pInt);
220706f2543Smrg
221706f2543SmrgIn case  a platform specific  mapping has to  be performed to  map the
222706f2543Smrgmemory allocated for the real  mode memory environment into a specific
223706f2543Smrglocation prior to executing the x86 real mode code a function
224706f2543Smrg
225706f2543Smrg        Bool MapCurrentInt10(xf86Int10InfoPtr pInt);
226706f2543Smrg
227706f2543Smrghas to  be provided. It will  be called by a  helper function whenever
228706f2543Smrgthe active entity changes. If the  vm86 mode is used it is most likely
229706f2543Smrgthat the 1MB real mode memory space located somewhere in the processes
230706f2543Smrgvirtual memory  will have to be  remapped to address 0  of the virtual
231706f2543Smrgmemory space.
232706f2543Smrg
233706f2543Smrg3.   void xf86FreeInt10(xf86Int10InfoPtr pInt);
234706f2543Smrg
235706f2543SmrgTo free all memory allocated for video BIOS calls of a specific entity
236706f2543Smrgthe function
237706f2543Smrg
238706f2543Smrg       void xf86FreeInt10(xf86Int10InfoPtr pInt);
239706f2543Smrg
240706f2543Smrgshould  be  provided.  If  the  entity  to  be  freed  was  mapped  by
241706f2543SmrgMapCurrentInt10() this mapping needs to be undone also.
242706f2543Smrg
243706f2543Smrg4. 
244706f2543Smrg   void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off)
245706f2543Smrg   void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num)
246706f2543Smrg
247706f2543Smrgxf86Int10AllocPages()  should  allocate  'num'  consecutive  page-size
248706f2543Smrgchunks of memory. In real mode memory space this range needs to occupy
249706f2543Smrgconsecutive addresses,  too. The function  must return the  address of
250706f2543Smrgthis memory.  The offset in real  mode memory needs to  be returned in
251706f2543Smrg'off'. If  no block of 'num'  pages are available  the function should
252706f2543Smrgreturn NULL.
253706f2543Smrg
254706f2543Smrgxf86Int10FreePages() will  free the  'num' pages starting  at 'pbase'.
255706f2543Smrg'num'  is  equal  to  the  number  of  pages  allocated  by  a  single
256706f2543Smrgxf86Int10AllocatePages()  call. 'pbase'  is the  address of  the range
257706f2543Smrgpreviously returned by xf86Int10AllocatePages().
258706f2543Smrg
259706f2543SmrgII. Emulator specific functions
260706f2543Smrg-------------------------------
261706f2543Smrg
262706f2543Smrg1. Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt);
263706f2543Smrg
264706f2543SmrgThis function will  be called from xf86InitInt10(). It  may be used to
265706f2543Smrgset  up   the  static  emulator   specific  part  of  the   real  mode
266706f2543Smrgenvironment. On success it should return TRUE.
267706f2543Smrg
268706f2543Smrg2. xf86ExecX86int10(xf86Int10InfoPtr pInt);
269706f2543Smrg
270706f2543SmrgThis function  gets called  to execute  an int call.  It may  call the
271706f2543Smrghelper function:
272706f2543Smrg
273706f2543Smrg       void setup_int(xf86Int10InfoPrt pInt);
274706f2543Smrg
275706f2543Smrgto copy the register values  to the emulator specific locations and to
276706f2543Smrgset up the non-static real mode execution environment.  On return from
277706f2543Smrgsetup_int()   'Int10Current'   holds   a   pointer  to   the   current
278706f2543Smrgxf86Int10InfoRec.
279706f2543Smrg
280706f2543SmrgIt should start execution by calling 
281706f2543Smrg
282706f2543Smrg       Bool int_handler(xf86Int10InfoPtr pInt);
283706f2543Smrg
284706f2543Smrgand if this function returns TRUE it should call whatever necessary to
285706f2543Smrgcontinue execution until a  'hlt' instruction is encountered.  To copy
286706f2543Smrgthe resulting register values back to the xf86Int10InfoRec structure
287706f2543Smrg
288706f2543Smrg     void finish_int(xf86Int10InfoPtr pInt);
289706f2543Smrg
290706f2543Smrgshould be called. 
291706f2543Smrg
292706f2543SmrgHelper  functions are  provided to  aid the  implementation of  a vm86
293706f2543Smrgcall:
294706f2543Smrg
295706f2543Smrg  Bool vm86_GP_fault(xf86Int10InfoPtr pInt);
296706f2543Smrg
297706f2543SmrgThis  function  handles  instructions  which  cause  a  vm86  call  to
298706f2543Smrgtrap.  PIO  access  is handled  by  the  in/out  calls as  defined  in
299706f2543Smrgcompiler.h. Optionally the PIO  instructions can be logged by defining
300706f2543SmrgPRINT_PORT in xf86int10.h. This is meant for debugging purposes.
301706f2543Smrg
302706f2543SmrgUnknown  instructions  and   'hlt'  cause  vm86_GP_fault()  to  return
303706f2543SmrgFALSE. Otherwise TRUE is returned.
304706f2543Smrg
305706f2543SmrgNote: This  function is  currently based on  the Linux vm86  call.  It
306706f2543Smrgmight have  to be modified  or even rewritten  for other OS.   So your
307706f2543Smrgmilage may vary.
308706f2543Smrg
309706f2543SmrgFunctions to dump memory, code, xf86 CPU register values and stack are
310706f2543Smrgalso provided.  Take a  look at  helper.c To view  a memory  range the
311706f2543Smrgfunction
312706f2543Smrg
313706f2543Smrg    void dprint(unsigned long start, unsigned long size)
314706f2543Smrg
315706f2543Smrgis provided. The use should be self explanatory.
316706f2543Smrg
317706f2543SmrgRegister  and memory  access functions  are provided  in helper_mem.c.
318706f2543SmrgThe PIO register access functions  can trap access to PCI config space
319706f2543Smrgaccess register (config method 1) if _PC is not defined.
320706f2543Smrg
321706f2543SmrgA header  file 'defines.h' is required to  define OS/emulator specific
322706f2543Smrgways  to access  memory and  xf86 CPU  registers: Defines  need  to be
323706f2543Smrgprovided     for    memory     byte/work/long     read/write    access
324706f2543Smrg(MEM_RB(name,addr),MEM_RW(name,addr),MEM_RL(name,addr),
325706f2543SmrgMEM_WB(name,addr,val),MEM_WL(name,addr,val),MEM_WL(name,addr,val))   of
326706f2543Smrgthe real mode memory environment. 'name' will contain a pointer to the
327706f2543Smrgcurrent   xf86Int10InfoRec.  Currently   defines  are   available  for
328706f2543Smrgvm86-mode under  Linux and x86emu.  They may be activated  by defining
329706f2543Smrg_X86EMU or _VM86_LINUX respectively.
330706f2543Smrg
331706f2543SmrgNote: Emulators usually are not able to pass this pointer when calling
332706f2543Smrgmemory  access functions.  In this  case a  global variable  should be
333706f2543Smrgdefined  which can  hold this  pointer. This  variable can  be  set in
334706f2543SmrgMapCurrentInt10().  It also  must be  set in  xf86InitInt10()  if this
335706f2543Smrgfunction  calls the  memory  access functions  either  directly or  by
336706f2543Smrgcalling  xf86ExecX86int10(pInt).   Defines   to  access  the  emulator
337706f2543Smrgspecific   xf86   CPU    register   locations   are   also   required:
338706f2543SmrgX86_EAX,...,X86_EFLAGS  for  access  of  the full  32  bit  registers,
339706f2543SmrgX86_AX...X86_FLAGS   for  access   of   the  16   bit  registers   and
340706f2543SmrgXF86_AL,XF86_BL,XF86_CL,XF86_DL  to  access  the  lower  byte  of  the
341706f2543SmrgAX,BX,CX and DX register.
342706f2543Smrg
343706f2543Smrg
344706f2543Smrg$XFree86: xc/programs/Xserver/hw/xfree86/int10/INT10.HOWTO,v 1.2 2000/02/08 13:13:22 eich Exp $
345