105b261ecSmrg
205b261ecSmrg                 INT10  X86 Real Mode executor
305b261ecSmrg                 =============================
405b261ecSmrg
505b261ecSmrg		         PRELIMINARY
605b261ecSmrg
705b261ecSmrgINT10 is  a XFree86  module for soft-booting  and executing  real mode
805b261ecSmrgint10 BIOS calls. The BIOS call code is largely untested, yet.
905b261ecSmrg
1005b261ecSmrg1. Usage
1105b261ecSmrg========
1205b261ecSmrg
1305b261ecSmrgTo   use   the   int10   module   in  a   driver   the   header   file
1405b261ecSmrgxfree86/os-support/int10/xf86int10.h must be included.
1505b261ecSmrg
1605b261ecSmrg a. Initialization
1705b261ecSmrg -----------------
1805b261ecSmrg
1905b261ecSmrgThe int10-executer gets initialized by calling:
2005b261ecSmrg
2105b261ecSmrg   xf86Int10InfoPtr xf86InitInt10(int entityIndex);
2205b261ecSmrg
2305b261ecSmrgThe  function  will soft-boot  any  non-primary  device  and return  a
2405b261ecSmrgpointer  to a  xf86Int10InfoRec on  success. If  anything fails  or if
2505b261ecSmrgint10 execution  is disabled by an  option in the  device section NULL
2605b261ecSmrgwill  be returned.   The driver  should store  this pointer  for later
2705b261ecSmrgcalls to other int10 module functions.
2805b261ecSmrg
2905b261ecSmrg b. Memory allocation
3005b261ecSmrg --------------------
3105b261ecSmrg
3205b261ecSmrgTo allocate memory in the real mode execution environment
3305b261ecSmrg    
3405b261ecSmrg   void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off);
3505b261ecSmrg
3605b261ecSmrgcan  be called.  It  allocates num  consecutive  pagesize chunks.   It
3705b261ecSmrgreturns the address of the allocated area. off is set to its offset in
3805b261ecSmrgthe real mode memory space.
3905b261ecSmrg
4005b261ecSmrg  void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num);
4105b261ecSmrg
4205b261ecSmrgIs used to free num pages beginning at pbase.
4305b261ecSmrg
4405b261ecSmrg c. Doing int10 BIOS calls
4505b261ecSmrg -------------------------
4605b261ecSmrg
4705b261ecSmrgThe BIOS call is executed by calling:
4805b261ecSmrg   
4905b261ecSmrg   void xf86ExecX86int10(xf86Int10InfoPtr pInt);
5005b261ecSmrg
5105b261ecSmrgThe number  of the interrupt (normally  10) and the  initial values of
5205b261ecSmrgthe ax, bx, cx, dx, si, di  and es x86-CPU registers can be set in the
5305b261ecSmrgxf86Int10InfoRec  passed to  the function.   On return  this structure
5405b261ecSmrgcontains the  exit values  of the registers  listed above and  the CPU
5505b261ecSmrgflag register.
5605b261ecSmrg
5705b261ecSmrg d. De-initializing
5805b261ecSmrg -----------------
5905b261ecSmrg
6005b261ecSmrgIf no further int10 calls are required for a certain chipset
6105b261ecSmrgthe driver should call:
6205b261ecSmrg
6305b261ecSmrg  void xf86FreeInt10(xf86Int10InfoPtr pInt);
6405b261ecSmrg
6505b261ecSmrgto free the memory allocated for real mode int10 calls.
6605b261ecSmrg
6705b261ecSmrg
6805b261ecSmrg2. Porting issues
6905b261ecSmrg=================
7005b261ecSmrg
7105b261ecSmrgThe int10 real mode executor is  designed to run on top of various x86
7205b261ecSmrgCPU emulators as well as in vm86  mode of a real x86 CPU. If used with
7305b261ecSmrga CPU  emulator the emulator and  CPU specific interfaces  can be held
7405b261ecSmrgseparate thus  requiring minimal efforts  to port the int10  module to
7505b261ecSmrgnew  platforms.   Currently  an  interface  to the  x86emu  real  mode
7605b261ecSmrgemulator is  provided.  Since  details of setting  up and  running the
7705b261ecSmrgvm86  mode   is  platform   dependent  both  the   platform  dependent
7805b261ecSmrgenvironment and the emulation layer  have to be ported. Several helper
7905b261ecSmrgfunctions are provided for that.
8005b261ecSmrg
8105b261ecSmrgA CPU emulator should meet certain requirements to be usable
8205b261ecSmrgfor the INT10 executor:
8305b261ecSmrg
8405b261ecSmrg1. It must trap  calls to intXX instructions and  pass execution to an
8505b261ecSmrg   external  function  which  is   allowed  to  modify  CPU  registers
8605b261ecSmrg   including  the instruction  pointer  (IP) before  returning to  the
8705b261ecSmrg   emulator for  continuing execution.  When the external  function is
8805b261ecSmrg   called the  IP must point to  the instruction past  the intXX call.
8905b261ecSmrg
9005b261ecSmrg2. The  emulator should  use externally  provided functions  to handle
9105b261ecSmrg   PIO.
9205b261ecSmrg
9305b261ecSmrg3.  The emulator  should be able to use  externally provided functions
9405b261ecSmrg to access memory  from the real mode memory  environment.  Note, that
9505b261ecSmrg the  vm86  mode  usually  requires  one hunk  of  consecutive  memory
9605b261ecSmrg starting at address  0 in the process virtual  memory space.  Thus if
9705b261ecSmrg this mode is to be used, the OS environment has to be able to provide
9805b261ecSmrg that, ie. it must be able to remap the processes virtual memory space
99ed6184dfSmrg onto itself.  If the emulator is able to handle memory access through
10005b261ecSmrg externally  provided functions the  real mode  process memory  can be
10105b261ecSmrg located anywhere  in the processes  virtual memory. It does  not even
10205b261ecSmrg have to be consecutive.
10305b261ecSmrg
10405b261ecSmrg4. The executor should terminate on encountering a 'hlt' instruction.
10505b261ecSmrg
10605b261ecSmrg
10705b261ecSmrgFunctions to implement:
10805b261ecSmrg
10905b261ecSmrgTo simplify development  the code has been split  into a general setup
11005b261ecSmrgpart and an emulator specific one. A generic setup code is provided in
11105b261ecSmrggeneric.c.  It  should be  usable  with  any  emulator satisfying  the
11205b261ecSmrgconditions mentioned  above. Therefore the following  section on int10
11305b261ecSmrgsetup may be skipped when porting int10 to new emulator.
11405b261ecSmrg
11505b261ecSmrgIf the  vm86() is to be used  no memory access functions  can be used.
11605b261ecSmrgTherefore the layout of the real mode memory image has to meet certain
11705b261ecSmrgrequirements. Therefore  when porting to  other platforms a  new setup
11805b261ecSmrgcode may  have to  be designed, too.  The following section  will give
11905b261ecSmrgguidelines how  this may be  done. A sample implementation  using SysV
12005b261ecSmrgIPC to  map the  appropriate real  mode memory image  to address  0 in
12105b261ecSmrgvirtual  address  space  just  prior  to execution  may  be  found  in
12205b261ecSmrgxfree86/os-support/linux/int10/linux.c.
12305b261ecSmrg
12405b261ecSmrgOn  non-PC like  platforms emulation  of certain  PC features  such as
12505b261ecSmrginitialization of  BIOS int vectors, sys_BIOS constants  or PCI config
12605b261ecSmrgmethod 1 can be turned on by defining _PC.
12705b261ecSmrg
12805b261ecSmrgI. Setup Code
12905b261ecSmrg-------------
13005b261ecSmrg
13105b261ecSmrgThis sets  up the real mode  memory image, calls the  emulator to POST
13205b261ecSmrgthe chipset if required and  maintains memory allocations in real mode
13305b261ecSmrgaddress space.
13405b261ecSmrg
13505b261ecSmrg1. xf86Int10InfoPtr xf86InitInt10(int entityIndex);
13605b261ecSmrg
13705b261ecSmrgThis  function should  first find  the screen  assigned to  the entity
13805b261ecSmrgcarrying entitiyIndex and then call
13905b261ecSmrg
14005b261ecSmrg       Bool int10skip(ScrnInfoPtr pScrn)
14105b261ecSmrg
14205b261ecSmrgto find out if the user  has requested not to initialize int10.  If so
14305b261ecSmrgxf86InitInt10()  should  return  NULL. Otherwise  an  xf86Int10InfoRec
14405b261ecSmrgshould be allocated.  This structure contains the following fields:
14505b261ecSmrg
14605b261ecSmrg    a. int entityIndex   - index of the entity whose BIOS is to be 
14705b261ecSmrg                           executed.
14805b261ecSmrg    b. int scrnIndex     - index of the screen assigned the entity.
14905b261ecSmrg    c. pointer cpuRegs   - pointer to a emulator/vm86-mode private 
15005b261ecSmrg                           structure.  May hold cpu register values 
15105b261ecSmrg                           for the emulator.
15205b261ecSmrg    d. CARD16 BIOSseg    - Video BIOS segment address.
15305b261ecSmrg    e. pointer private   - pointer to a os specific data structure.
15405b261ecSmrg    f. struct _int10Mem* - pointer to a structure to hold the memory
15505b261ecSmrg                           access functions for use by an emulator.
15605b261ecSmrg    g. int num           - number of the int to be called.
15705b261ecSmrg    h. int ax..es,flags  - CPU register values to pass to int-call.
15805b261ecSmrg
15905b261ecSmrgThe Init  function should initialize  a-f. To initialize  the emulator
16005b261ecSmrgspecific execute environment the function
16105b261ecSmrg
16205b261ecSmrg     Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt)
16305b261ecSmrg
16405b261ecSmrgshould be called. If this function returns FALSE any already allocated
16505b261ecSmrgmemory should be freed and xf86Int10Init(0 should exit returning NULL.
16605b261ecSmrg
16705b261ecSmrgIf the  platform has  a PC  like system BIOS  it may  be copied  to or
16805b261ecSmrgmapped into memory  locations SYS_BIOS to SYS_SIZE-1 of  the real mode
16905b261ecSmrgmemory environment of this process. Otherwise the helper function: 
17005b261ecSmrg
17105b261ecSmrgint setup_system_bios(CARD32 base_addr); 
17205b261ecSmrg
17305b261ecSmrgmay be  called to set  up a rudimentary  system BIOS sufficient  to be
17405b261ecSmrgused to  boot video BIOSes.   base_addr specifies the  virtual address
17505b261ecSmrgcorresponding to SYS_BIOS in the  real mode environment.  If a PC-like
17605b261ecSmrgint vector and BIOS data area is available it should be copied to 0 to
17705b261ecSmrgLOW_PAGE_SIZE of the entities real mode environment.  In this case the
17805b261ecSmrgvideo interrupt  related entries should  be reset for  all non-primary
17905b261ecSmrgcards by calling:
18005b261ecSmrg
18105b261ecSmrgvoid reset_int_vect(xf86Int10InfoPtr pInt); To initialize the
18205b261ecSmrg
18305b261ecSmrgcorrect video BIOS  entry points the BIOS must  be warm-booted.  If no
18405b261ecSmrgPC-like int vector is available one can be set up by calling 
18505b261ecSmrg
18605b261ecSmrgvoid setup_int_vect(xf86Int10InfoPtr pInt); 
18705b261ecSmrg
18805b261ecSmrgIn this  case the  video BIOS  has to be  warm-booted always.   If the
18905b261ecSmrgvideo BIOS  for this entity has  been installed during boot  it may be
19005b261ecSmrgmapped (or  copied) directly to the  correct address in  the real mode
19105b261ecSmrgmemory environment.  Otherwise
19205b261ecSmrg
19305b261ecSmrgint mapPciRom(xf86Int10InfoPtr pInt, unsigned char * address); 
19405b261ecSmrg
19505b261ecSmrgshould  be called  to copy  the BIOS  image from  PCI  ROM.  'address'
19605b261ecSmrgspecifies the address this image should be copied to. Sufficient space
19705b261ecSmrgto  hold an entire  BIOS image  should be  allocated prior  to calling
19805b261ecSmrgmapPciRom(). This function  will return the size of  the BIOS image in
19905b261ecSmrgbytes  if  it   was  able  to  successfully  copy   the  image  and  0
20005b261ecSmrgotherwise. To create a well defined point to exit the softbooter
20105b261ecSmrg
20205b261ecSmrgvoid set_return_trap(xf86Int10Ptr pInt); 
20305b261ecSmrg
20405b261ecSmrgmay be called.  It sets up a 'hlt' instruction  in the emulator memory
20505b261ecSmrgjust above the BIOS variable area. Before entering real mode execution
20605b261ecSmrgthis address will be pushed onto  the return stack.  If the BIOS needs
20705b261ecSmrgto be  warm-booted this should be done  before leaving xf86InitInt10()
20805b261ecSmrgby setting num in the xf86Int10InfoRec to 0xe6 and calling
20905b261ecSmrg
21005b261ecSmrgvoid xf86ExecX86int10(xf86Int10IfoPtr pInt); 
21105b261ecSmrg
21205b261ecSmrgThe  implementation of this  function will  be discussed  below.  This
21305b261ecSmrgfunction  should be  wrapped  by calls  to void  LockLegacyVGA(screen,
21405b261ecSmrglegacyVGAPtr vga); and void UnlockLegacyVGA(screen, legacyVGAPtr vga);
21505b261ecSmrgThe struct  vga is  used to hold  the state  of the legacy  VGA access
21605b261ecSmrgregisters  if  a legacy  VGA  device  exists.  xf86InitInt10()  should
21705b261ecSmrgreturn a pointer to the xf86Int10InfoRec allocated.
21805b261ecSmrg
21905b261ecSmrg2. Bool MapCurrentInt10(xf86Int10InfoPtr pInt);
22005b261ecSmrg
22105b261ecSmrgIn case  a platform specific  mapping has to  be performed to  map the
22205b261ecSmrgmemory allocated for the real  mode memory environment into a specific
22305b261ecSmrglocation prior to executing the x86 real mode code a function
22405b261ecSmrg
22505b261ecSmrg        Bool MapCurrentInt10(xf86Int10InfoPtr pInt);
22605b261ecSmrg
22705b261ecSmrghas to  be provided. It will  be called by a  helper function whenever
22805b261ecSmrgthe active entity changes. If the  vm86 mode is used it is most likely
22905b261ecSmrgthat the 1MB real mode memory space located somewhere in the processes
23005b261ecSmrgvirtual memory  will have to be  remapped to address 0  of the virtual
23105b261ecSmrgmemory space.
23205b261ecSmrg
23305b261ecSmrg3.   void xf86FreeInt10(xf86Int10InfoPtr pInt);
23405b261ecSmrg
23505b261ecSmrgTo free all memory allocated for video BIOS calls of a specific entity
23605b261ecSmrgthe function
23705b261ecSmrg
23805b261ecSmrg       void xf86FreeInt10(xf86Int10InfoPtr pInt);
23905b261ecSmrg
24005b261ecSmrgshould  be  provided.  If  the  entity  to  be  freed  was  mapped  by
24105b261ecSmrgMapCurrentInt10() this mapping needs to be undone also.
24205b261ecSmrg
24305b261ecSmrg4. 
24405b261ecSmrg   void * xf86Int10AllocPages(xf86Int10InfoPtr pInt,int num, int *off)
24505b261ecSmrg   void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num)
24605b261ecSmrg
24705b261ecSmrgxf86Int10AllocPages()  should  allocate  'num'  consecutive  page-size
24805b261ecSmrgchunks of memory. In real mode memory space this range needs to occupy
24905b261ecSmrgconsecutive addresses,  too. The function  must return the  address of
25005b261ecSmrgthis memory.  The offset in real  mode memory needs to  be returned in
25105b261ecSmrg'off'. If  no block of 'num'  pages are available  the function should
25205b261ecSmrgreturn NULL.
25305b261ecSmrg
25405b261ecSmrgxf86Int10FreePages() will  free the  'num' pages starting  at 'pbase'.
25505b261ecSmrg'num'  is  equal  to  the  number  of  pages  allocated  by  a  single
25605b261ecSmrgxf86Int10AllocatePages()  call. 'pbase'  is the  address of  the range
25705b261ecSmrgpreviously returned by xf86Int10AllocatePages().
25805b261ecSmrg
25905b261ecSmrgII. Emulator specific functions
26005b261ecSmrg-------------------------------
26105b261ecSmrg
26205b261ecSmrg1. Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt);
26305b261ecSmrg
26405b261ecSmrgThis function will  be called from xf86InitInt10(). It  may be used to
26505b261ecSmrgset  up   the  static  emulator   specific  part  of  the   real  mode
26605b261ecSmrgenvironment. On success it should return TRUE.
26705b261ecSmrg
26805b261ecSmrg2. xf86ExecX86int10(xf86Int10InfoPtr pInt);
26905b261ecSmrg
27005b261ecSmrgThis function  gets called  to execute  an int call.  It may  call the
27105b261ecSmrghelper function:
27205b261ecSmrg
27305b261ecSmrg       void setup_int(xf86Int10InfoPrt pInt);
27405b261ecSmrg
27505b261ecSmrgto copy the register values  to the emulator specific locations and to
27605b261ecSmrgset up the non-static real mode execution environment.  On return from
27705b261ecSmrgsetup_int()   'Int10Current'   holds   a   pointer  to   the   current
27805b261ecSmrgxf86Int10InfoRec.
27905b261ecSmrg
28005b261ecSmrgIt should start execution by calling 
28105b261ecSmrg
28205b261ecSmrg       Bool int_handler(xf86Int10InfoPtr pInt);
28305b261ecSmrg
28405b261ecSmrgand if this function returns TRUE it should call whatever necessary to
28505b261ecSmrgcontinue execution until a  'hlt' instruction is encountered.  To copy
28605b261ecSmrgthe resulting register values back to the xf86Int10InfoRec structure
28705b261ecSmrg
28805b261ecSmrg     void finish_int(xf86Int10InfoPtr pInt);
28905b261ecSmrg
29005b261ecSmrgshould be called. 
29105b261ecSmrg
29205b261ecSmrgHelper  functions are  provided to  aid the  implementation of  a vm86
29305b261ecSmrgcall:
29405b261ecSmrg
29505b261ecSmrg  Bool vm86_GP_fault(xf86Int10InfoPtr pInt);
29605b261ecSmrg
29705b261ecSmrgThis  function  handles  instructions  which  cause  a  vm86  call  to
29805b261ecSmrgtrap.  PIO  access  is handled  by  the  in/out  calls as  defined  in
29905b261ecSmrgcompiler.h. Optionally the PIO  instructions can be logged by defining
30005b261ecSmrgPRINT_PORT in xf86int10.h. This is meant for debugging purposes.
30105b261ecSmrg
30205b261ecSmrgUnknown  instructions  and   'hlt'  cause  vm86_GP_fault()  to  return
30305b261ecSmrgFALSE. Otherwise TRUE is returned.
30405b261ecSmrg
30505b261ecSmrgNote: This  function is  currently based on  the Linux vm86  call.  It
30605b261ecSmrgmight have  to be modified  or even rewritten  for other OS.   So your
307ed6184dfSmrgmileage may vary.
30805b261ecSmrg
30905b261ecSmrgFunctions to dump memory, code, xf86 CPU register values and stack are
31005b261ecSmrgalso provided.  Take a  look at  helper.c To view  a memory  range the
31105b261ecSmrgfunction
31205b261ecSmrg
31305b261ecSmrg    void dprint(unsigned long start, unsigned long size)
31405b261ecSmrg
31505b261ecSmrgis provided. The use should be self explanatory.
31605b261ecSmrg
31705b261ecSmrgRegister  and memory  access functions  are provided  in helper_mem.c.
31805b261ecSmrgThe PIO register access functions  can trap access to PCI config space
31905b261ecSmrgaccess register (config method 1) if _PC is not defined.
32005b261ecSmrg
32105b261ecSmrgA header  file 'defines.h' is required to  define OS/emulator specific
32205b261ecSmrgways  to access  memory and  xf86 CPU  registers: Defines  need  to be
32305b261ecSmrgprovided     for    memory     byte/work/long     read/write    access
32405b261ecSmrg(MEM_RB(name,addr),MEM_RW(name,addr),MEM_RL(name,addr),
32505b261ecSmrgMEM_WB(name,addr,val),MEM_WL(name,addr,val),MEM_WL(name,addr,val))   of
32605b261ecSmrgthe real mode memory environment. 'name' will contain a pointer to the
32705b261ecSmrgcurrent   xf86Int10InfoRec.  Currently   defines  are   available  for
32805b261ecSmrgvm86-mode under  Linux and x86emu.  They may be activated  by defining
32905b261ecSmrg_X86EMU or _VM86_LINUX respectively.
33005b261ecSmrg
33105b261ecSmrgNote: Emulators usually are not able to pass this pointer when calling
33205b261ecSmrgmemory  access functions.  In this  case a  global variable  should be
33305b261ecSmrgdefined  which can  hold this  pointer. This  variable can  be  set in
33405b261ecSmrgMapCurrentInt10().  It also  must be  set in  xf86InitInt10()  if this
33505b261ecSmrgfunction  calls the  memory  access functions  either  directly or  by
33605b261ecSmrgcalling  xf86ExecX86int10(pInt).   Defines   to  access  the  emulator
33705b261ecSmrgspecific   xf86   CPU    register   locations   are   also   required:
33805b261ecSmrgX86_EAX,...,X86_EFLAGS  for  access  of  the full  32  bit  registers,
33905b261ecSmrgX86_AX...X86_FLAGS   for  access   of   the  16   bit  registers   and
34005b261ecSmrgXF86_AL,XF86_BL,XF86_CL,XF86_DL  to  access  the  lower  byte  of  the
34105b261ecSmrgAX,BX,CX and DX register.
34205b261ecSmrg
34305b261ecSmrg
34405b261ecSmrg$XFree86: xc/programs/Xserver/hw/xfree86/int10/INT10.HOWTO,v 1.2 2000/02/08 13:13:22 eich Exp $
345