The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386ps2/abios.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1991 Carnegie Mellon University
    4  * Copyright (c) 1991 IBM Corporation 
    5  * All Rights Reserved.
    6  * 
    7  * Permission to use, copy, modify and distribute this software and its
    8  * documentation is hereby granted, provided that both the copyright
    9  * notice and this permission notice appear in all copies of the
   10  * software, derivative works or modified versions, and any portions
   11  * thereof, and that both notices appear in supporting documentation,
   12  * and that the name IBM not be used in advertising or publicity 
   13  * pertaining to distribution of the software without specific, written
   14  * prior permission.
   15  * 
   16  * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   17  * CONDITION.  CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
   18  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   19  * 
   20  * Carnegie Mellon requests users of this software to return to
   21  * 
   22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   23  *  School of Computer Science
   24  *  Carnegie Mellon University
   25  *  Pittsburgh PA 15213-3890
   26  * 
   27  * any improvements or extensions that they make and grant Carnegie Mellon
   28  * the rights to redistribute these changes.
   29  */
   30 
   31 /*
   32  * HISTORY
   33  * $Log:        abios.c,v $
   34  * Revision 2.3  93/03/11  14:08:38  danner
   35  *      u_long -> u_int
   36  *      [93/03/09            danner]
   37  * 
   38  *      [93/03/09            danner]
   39  * 
   40  * Revision 2.2  93/02/04  07:58:30  danner
   41  *      Integrate PS2 code from IBM.
   42  *      [93/01/18            prithvi]
   43  * 
   44  */
   45 
   46 #include <sys/types.h>
   47 
   48 #include <mach/i386/vm_types.h>
   49 #include <mach/i386/vm_param.h>
   50 #include <i386/seg.h>
   51 #include <i386ps2/abios.h>
   52 
   53 /*
   54  * We must adjust the bottom of the memory hole here.
   55  * cnvmem doesn't count all the memory that ABIOS uses.
   56  */
   57 extern vm_offset_t      hole_start;
   58 
   59 #define MAX_SIZE        0xffff
   60 #define BAD_DESCRIPT    0xffff
   61 #define PTOV(x)         (phystokv(x))
   62 
   63 /*
   64  * DEBUG must be defined if ABIOS_DEBUG is (get_dev is called from test_calls)
   65  */
   66 #define ABIOS_DEBUG 1
   67 
   68 #if defined(ABIOS_DEBUG) && !defined(DEBUG)
   69 #define DEBUG 1
   70 #endif
   71 
   72 #define MAXSEL 20
   73 static struct selector_array    code_array[MAXSEL] = {0};
   74 static struct selector_array    data_array[MAXSEL] = {0};
   75 extern struct fake_descriptor   gdt[];
   76 struct Abios_header *abios_info = 0;
   77 
   78 char *make_32();
   79 u_short allocate_gdt();
   80 
   81 #ifdef DEBUG
   82 #define DEBUGF(x,y)     if (x) y
   83 char *get_dev();
   84 
   85 int abiosdebug = 0;
   86 #else
   87 #define DEBUGF(x,y)
   88 #endif
   89 
   90 static struct real_descriptor   *gdt_hint
   91                 = (struct real_descriptor *) &gdt[ABIOS_FIRST_AVAIL_SEL];
   92                                         /* a hint for allocate_gdt */
   93 
   94 /* put the variables referenced in init_ps2 in data */
   95 
   96 abios_init()
   97 {
   98         struct Abios_header *abhp = abios_info;
   99         int     rc,i;
  100         int     data_count;
  101 
  102         DEBUGF(abiosdebug,printf("abhp = %x\n",abhp));
  103         if (abhp == 0) {
  104                 printf("ABIOS not found. Not initialized!\n");
  105                 return;
  106         }
  107         abhp = (struct Abios_header *) PTOV(abhp);
  108 
  109         /* map the abios data area into virtual memory */
  110         system_param_p = (struct System_parameter_table *)
  111                         PTOV(abhp->sys_table);
  112 
  113         /* build addresses to get to the abios common data area */
  114         anchor_pointer = (struct Common_data_area_head *)
  115                                         PTOV(abhp->common_block);
  116 
  117         if ((anchor_seg = allocate_gdt()) == BAD_DESCRIPT) {
  118                 printf("out of gdt for anchor_seg\n");
  119                 return(-1);
  120         } 
  121         make_gdt_desc(anchor_seg,
  122                       (unsigned int) anchor_pointer,
  123                       anchor_pointer->data_ptr_0+7,
  124                       ACC_DATA_W,
  125                       0);
  126 
  127 
  128         /* copy to the fake table before fixups.. */
  129         bcopy(anchor_pointer,abios_common,anchor_pointer->data_ptr_0+8);
  130 
  131         /*
  132          * now fix up the logical device pointers
  133          */
  134         for (i=0; i < anchor_pointer->number_logical_ids; i++) {
  135                 fixup(&logical_device(i+1),i+1);
  136         }
  137 
  138         /*
  139          * fix up the data pointers
  140          */
  141         data_count = *(u_short *)(data_pointer0 + 1);
  142         for (i=0 ; i < data_count; i++) {
  143                 struct Data_pointer *dp = &data_pointer(i);
  144 
  145                 dp->dp_segment = (dp->dp_offset >> 4) + (dp->dp_segment << 12);
  146                 dp->dp_offset &= 0xf;
  147                 abios_convert(data_array, &(dp->dp_offset),
  148                               ACC_DATA_W, dp->dp_length);
  149         }
  150 
  151         /*
  152          * build the fake anchor_pointer table
  153          */
  154         anchor_pointer = (struct Common_data_area_head *) abios_common;
  155         for (i=0; i < anchor_pointer->number_logical_ids; i++) {
  156                 logical_device(i+1).device_block = (struct Device_block *)
  157                                 make_32(logical_device(i+1).device_block);
  158                 logical_device(i+1).function_transfer_table = 
  159                      (struct Function_transfer_table *)
  160                         make_32(logical_device(i+1).function_transfer_table);
  161         }
  162 
  163         /*
  164          * fixup the common entry point stuff
  165          */
  166         abios_convert(code_array,&(system_param_p->common_start),
  167                       ACC_CODE_R, MAX_SIZE);
  168         abios_convert(code_array,&(system_param_p->common_interrupt),
  169                       ACC_CODE_R, MAX_SIZE);
  170         abios_convert(code_array,&(system_param_p->common_timeout),
  171                       ACC_CODE_R, MAX_SIZE);
  172         return(0);
  173 }
  174 
  175 abios_common_start(request,flags)
  176         struct generic_request *request;
  177         int     flags;
  178 {
  179         abios_xlate(system_param_p->common_start,request,flags);
  180 }
  181 
  182 abios_common_interrupt(request,flags)
  183         struct generic_request *request;
  184         int     flags;
  185 {
  186         abios_xlate(system_param_p->common_interrupt,request,flags);
  187 }
  188 
  189 abios_common_timeout(request,flags)
  190         struct generic_request *request;
  191         int     flags;
  192 {
  193         abios_xlate(system_param_p->common_timeout,request,flags);
  194 }
  195 
  196 abios_next_LID(dev_id,last_LID)
  197         int     last_LID;
  198 {
  199         int     i;
  200         struct Device_block *db;
  201 
  202         if (abios_info == 0)
  203                 return(0);      /* no abios - no LIDs */
  204 
  205         for (i=last_LID+1; i <= anchor_pointer->number_logical_ids; i++) {
  206                 if (db = logical_device(i).device_block) {
  207                         if (db->device_id == dev_id) {
  208                                 return(i);
  209                         }
  210                 }
  211         }
  212         /* no LID found */
  213         return(0);
  214 }
  215         
  216 abios_xlate(abios_routine,request,flags)
  217         char    *abios_routine;
  218         struct  generic_request *request;
  219         int     flags;
  220 {
  221         u_short selector;
  222         u_int   req_addr;
  223         u_int   data_addr;
  224         u_int   save_data = 0;
  225         int     i,s;
  226 
  227         selector = allocate_gdt();
  228         if (selector == 0) {
  229                 panic("abios_xlate: out of selectors");
  230         }
  231         make_gdt_desc(selector,
  232                       (unsigned int) request,
  233                       request->r_current_req_blck_len,
  234                       ACC_DATA_W,
  235                       0);
  236 
  237         req_addr = selector << 16;
  238         if ((flags & LOG_POINTER) && ((request->r_function == ABIOS_READ) ||
  239                  (request->r_function == ABIOS_WRITE) ||
  240                          (request->r_function == ABIOS_ADDITIONAL_XFER))) {
  241                 u_short data_select = allocate_gdt();
  242                 if (data_select == 0) {
  243                         panic("abios_xlate: out of selectors");
  244                 }
  245                 data_addr = *((u_int *)&request->g_data_offset);
  246                 make_gdt_desc(data_select,
  247                               data_addr,
  248                               MAX_SIZE,
  249                               ACC_DATA_W,
  250                               0);
  251                 request->g_data_offset = 0;
  252                 request->g_data_selector = data_select;
  253                 save_data++;
  254         }
  255                 
  256         req_addr = selector << 16;
  257 
  258         abios_call(0,0,req_addr,anchor_seg,abios_routine,0,0,0,0);
  259 
  260         if (save_data) {
  261                 free_gdt(request->g_data_selector);
  262                 *(u_int *)&request->g_data_offset = data_addr;
  263         }
  264         free_gdt(selector);
  265 }
  266 
  267 static int      abios_last_addr = 0;
  268 static struct Function_transfer_table *abios_ftt_array[50];
  269 
  270 fixup(device,LID)
  271         struct Logical_device *device;
  272         int     LID;
  273 {
  274         struct Function_transfer_table *ftt =
  275                 (struct Function_transfer_table *)make_32
  276                                         (device->function_transfer_table);
  277         struct Device_block *db = (struct Device_block *)
  278                                         make_32(device->device_block);
  279         int i;
  280         int done;
  281 
  282         DEBUGF(abiosdebug,printf("LID %x",LID));
  283         if (ftt) {
  284                 DEBUGF(abiosdebug,printf(", %d functions, ftt=%x",ftt->function_count,ftt));
  285                 done = 0;
  286                 for (i=0; i < abios_last_addr; i++) {
  287                         if (ftt == abios_ftt_array[i]) {
  288                                 done = 1;
  289                                 DEBUGF(abiosdebug,printf(" (fixups already done)"));
  290                                 break;
  291                         }
  292                 }
  293                 if (!done) {
  294                  abios_ftt_array[abios_last_addr++] = ftt;
  295                  abios_convert(code_array,&(ftt->start),
  296                                ACC_CODE_R, MAX_SIZE);
  297                  abios_convert(code_array,&(ftt->interrupt),
  298                                ACC_CODE_R, MAX_SIZE);
  299                  abios_convert(code_array,&(ftt->timeout),
  300                                ACC_CODE_R, MAX_SIZE);
  301                 
  302                  /*
  303                   * first fix up the FTT
  304                   */
  305                  for (i=0; i < ftt->function_count; i++) {
  306                         abios_convert(code_array,&(ftt->function_call(i)),
  307                                       ACC_CODE_R, MAX_SIZE);
  308                  }
  309                 }
  310                 abios_convert(data_array,&(device->function_transfer_table),
  311                               ACC_DATA_W, MAX_SIZE);
  312         }
  313         if (device->device_block) {
  314                 DEBUGF(abiosdebug,printf(", %s",get_dev(db->device_id)));
  315                 abios_convert(data_array,&(device->device_block),
  316                               ACC_DATA_W, MAX_SIZE);
  317         }
  318         DEBUGF(abiosdebug,printf("\n"));
  319 }
  320 
  321 struct far_pointer {
  322         u_short offset;
  323         u_short selector;
  324 };
  325 
  326 abios_convert(array,far_ptr,type,size)
  327         struct  selector_array *array;
  328         struct  far_pointer *far_ptr;
  329 {
  330         if (*(unsigned long *)far_ptr) {
  331                 far_ptr->selector = 
  332                                 get_selector(array,far_ptr->selector,type,size);
  333         }
  334 }
  335 
  336 get_selector(array,segment,type,size)
  337         struct selector_array *array;
  338         u_short segment;
  339 {
  340         vm_offset_t addr;
  341         int     count = 0;
  342 
  343         while (array->selector) {
  344                 if (array->segment == segment) {
  345                         return(array->selector);
  346                 }
  347                 array++;
  348                 count++;
  349         }
  350         if (count == MAXSEL) {
  351                 panic(" over allocated array\n");
  352         }
  353         array->selector = allocate_gdt();
  354         array->segment = segment;
  355         if (array->selector == 0) {
  356                 panic(" out of selectors\n");
  357         }
  358         addr = (vm_offset_t) make_32(segment << 16);
  359         make_gdt_desc(array->selector,
  360                       addr,
  361                       size,
  362                       type,
  363                       0);
  364 
  365         /*
  366          * Adjust hole_start to be below the lowest segment
  367          * mapped here.  But don`t count segments below 0x1000 -
  368          * we don`t use that for paging anyway.  See i386_init.
  369          *
  370          * Addr is a virtual address; hole_start is physical.
  371          */
  372         addr = kvtophys(addr);
  373         if (addr >= 0x1000) {
  374             if (hole_start > addr)
  375                 hole_start = addr;
  376         }
  377         return(array->selector);
  378 }
  379 
  380 /*
  381  * make_32 translates a dos real mode pointer (16 bit segment/16 bit offset)
  382  *  into a 386 flat mode paged vm pointer (32 bits).
  383  *  Called from several abios_init routines.
  384  */
  385 char *
  386 make_32(value)
  387         u_int value;
  388 {
  389         u_int phys = REALTOPHYS(value);
  390         return(phys?(char *)PTOV(phys):(char *)0);
  391 }
  392 
  393 void display_request(rb_ptr)
  394 struct generic_request *rb_ptr;
  395 {
  396 
  397         printf("The address of request block = %x\n\n",rb_ptr);
  398         printf("The function = %d\n",rb_ptr->r_function);
  399         printf("Current_req_block_len = %x\n",rb_ptr->r_current_req_blck_len);
  400         printf("Logical_id = %x\n",rb_ptr->r_logical_id);
  401         printf("Device ID = %x\n\n",rb_ptr->r_device_id);
  402         printf("Unit = %x\n",rb_ptr->r_unit);
  403         printf("Return_code = %x\n",rb_ptr->r_return_code);
  404         printf("Time_out = %x\n",rb_ptr->r_time_out);
  405 }
  406 
  407 
  408 
  409 #ifdef DEBUG
  410 
  411 /*
  412  * print the ascii string for the abios device type found
  413  */
  414 static char *device_name[] = {
  415         "ABIOS internal call",  /* 0x00 */
  416         "diskette",             /* 0x01 */
  417         "disk",                 /* 0x02 */
  418         "video",                /* 0x03 */
  419         "keyboard",             /* 0x04 */
  420         "parallel port",        /* 0x05 */
  421         "async port",           /* 0x06 */
  422         "system timer",         /* 0x07 */
  423         "real-time clock",      /* 0x08 */
  424         "system services",      /* 0x09 */
  425         "NMI",                  /* 0x0a */
  426         "mouse",                /* 0x0b */
  427         "reserved (0x0c)",      /* 0x0c */
  428         "reserved (0x0d)",      /* 0x0d */
  429         "NVRAM",                /* 0x0e */
  430         "DMA",                  /* 0x0f */
  431         "POS",                  /* 0x10 */
  432         "reserved (0x11)",      /* 0x11 */
  433         "reserved (0x12)",      /* 0x12 */
  434         "reserved (0x13)",      /* 0x13 */
  435         "reserved (0x14)",      /* 0x14 */
  436         "reserved (0x15)",      /* 0x15 */
  437         "keyboard security",    /* 0x16 */
  438         "reserved (0x17)",      /* 0x17 */
  439 };
  440 
  441 static int known_device_ids=(sizeof(device_name)/sizeof(device_name[0]));
  442 
  443 char *
  444 get_dev(type)
  445         u_int   type;
  446 {
  447         if (type >= known_device_ids) {
  448                 static char buffer[] = "(unknown 0x--)";
  449                 static char hex[] = "0123456789ABCDEF";
  450                 buffer[11] = hex[(type>>4)&0xf];
  451                 buffer[12] = hex[type&0xf];
  452                 return(buffer);
  453         }
  454 
  455         return(device_name[type]);
  456 }
  457 #endif /* DEBUG */
  458 
  459 #ifdef ABIOS_DEBUG
  460 
  461 /* the following code is for testing only!!! */
  462 static char *
  463 map_irq (irq)
  464         u_char  irq;
  465 {
  466         static char     buffer[30] = "irq00";
  467         if (irq == 0xff) {
  468                 return("NoInt");
  469         }
  470         if (irq == 0xfe) {
  471                 return("NMI  ");
  472         }
  473         buffer[3] = irq/10 + '';
  474         buffer[4] = irq%10 + '';
  475         return(buffer);
  476 }
  477 
  478 static char *
  479 map_arb (arb)
  480         u_char  arb;
  481 {
  482         static char     buffer[30] = "arb00 ";
  483         if (arb == 0xff) {
  484                 return("NoArb");
  485         }
  486         buffer[3] = arb/10 + '';
  487         buffer[4] = arb%10 + '';
  488         return(buffer);
  489 }
  490 
  491 test_call()
  492 {
  493         int     i;
  494         struct  generic_request req;
  495 
  496 
  497         /* LID 1 is a dummy, LID 2 would call cause 'infinite' recursion..*/
  498         for (i=2; i <= anchor_pointer->number_logical_ids; i++) {
  499                 int     dev = ABIOS_ID;
  500 
  501                 if (logical_device(i).device_block) {
  502                         dev = logical_device(i).device_block->device_id;
  503                 }
  504 
  505                 if (dev != ABIOS_ID) {
  506                         req.r_current_req_blck_len = 
  507                                                 sizeof(struct generic_request);
  508                         req.r_logical_id = i;
  509                         req.r_unit = 0;
  510                         req.r_function = ABIOS_LOGICAL_PARAMETER;
  511                         req.r_return_code = ABIOS_UNDEFINED;
  512                         abios_common_start(&req,0);
  513                 } else {
  514                         req.r_hardware_intr = 0xff;
  515                         req.r_arbitration_level = 0xff;
  516                         req.r_number_units = 0;
  517                         req.r_request_block_length =
  518                                          sizeof(struct generic_request);
  519                         req.r_logical_id_flags = 0;
  520                         req.r_return_code = 0;
  521                 }
  522                 printf("device %02x LID %02x",dev,i);
  523                 if (req.r_return_code == 0) {
  524                         printf(" %s %s units=%d size=%3d flags=%04x",
  525                          map_irq(req.r_hardware_intr), 
  526                          map_arb(req.r_arbitration_level),req.r_number_units,
  527                             req.r_request_block_length,req.r_logical_id_flags);
  528                 } else {
  529                         printf("ERROR, rc=0x%04x",req.r_return_code);
  530                 } 
  531                 printf(": %s\n",get_dev(dev));
  532         }
  533 }
  534 #endif /* ABIOS_DEBUG */
  535 
  536 
  537 int_on_ABIOS()
  538 {
  539   panic("interrupt on ABIOS stack");
  540   /* NOTREACHED */
  541 }
  542 
  543 trap_on_ABIOS()
  544 {
  545   panic("trap on ABIOS stack");
  546   /* NOTREACHED */
  547 }
  548 

Cache object: 19e9ce80f29aee88eb9124a462121da4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.