]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/bios32.c
pc/ether*: use 64-bit physical addresses and check pci membar types and sizes
[plan9front.git] / sys / src / 9 / pc / bios32.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7
8 #define VFLAG(...)      if(vflag) print(__VA_ARGS__)
9
10 #define UPTR2INT(p)     ((uintptr)(p))
11
12 #define l16get(p)       (((p)[1]<<8)|(p)[0])
13 #define l32get(p)       (((u32int)l16get(p+2)<<16)|l16get(p))
14
15 static int vflag = 0;
16
17 typedef struct BIOS32sdh {              /* BIOS32 Service Directory Header */
18         u8int   signature[4];           /* "_32_" */
19         u8int   physaddr[4];            /* physical address of entry point */
20         u8int   revision;
21         u8int   length;                 /* of header in paragraphs */
22         u8int   checksum;               /* */
23         u8int   reserved[5];
24 } BIOS32sdh;
25
26 typedef struct BIOS32si {               /* BIOS32 Service Interface */
27         u8int*  base;                   /* base address of service */
28         int     length;                 /* length of service */
29         u32int  offset;                 /* service entry-point from base */
30
31         u16int  ptr[3];                 /* far pointer m16:32 */
32 } BIOS32si;
33
34 static Lock bios32lock;
35 static u16int bios32ptr[3];
36 static void* bios32entry;
37
38 int
39 bios32ci(BIOS32si* si, BIOS32ci* ci)
40 {
41         int r;
42
43         lock(&bios32lock);
44         r = bios32call(ci, si->ptr);
45         unlock(&bios32lock);
46
47         return r;
48 }
49
50 static int
51 bios32locate(void)
52 {
53         uintptr ptr;
54         BIOS32sdh *sdh;
55
56         VFLAG("bios32link\n");
57         if((sdh = sigsearch("_32_", sizeof(BIOS32sdh))) == nil)
58                 return -1;
59         VFLAG("sdh @ %#p, entry %#ux\n", sdh, l32get(sdh->physaddr));
60
61         bios32entry = vmap(l32get(sdh->physaddr), 4096+1);
62         VFLAG("entry @ %#p\n", bios32entry);
63         ptr = UPTR2INT(bios32entry);
64         bios32ptr[0] = ptr & 0xffff;
65         bios32ptr[1] = (ptr>>16) & 0xffff;
66         bios32ptr[2] = KESEL;
67         VFLAG("bios32link: ptr %ux %ux %ux\n",
68                 bios32ptr[0], bios32ptr[1], bios32ptr[2]);
69
70         return 0;
71 }
72
73 void
74 BIOS32close(BIOS32si* si)
75 {
76         vunmap(si->base, si->length);
77         free(si);
78 }
79
80 BIOS32si*
81 bios32open(char* id)
82 {
83         uint ptr;
84         BIOS32ci ci;
85         BIOS32si *si;
86
87         lock(&bios32lock);
88         if(bios32ptr[2] == 0 && bios32locate() < 0){
89                 unlock(&bios32lock);
90                 return nil;
91         }
92
93         VFLAG("bios32si: %s\n", id);
94         memset(&ci, 0, sizeof(BIOS32ci));
95         ci.eax = (id[3]<<24|(id[2]<<16)|(id[1]<<8)|id[0]);
96
97         bios32call(&ci, bios32ptr);
98         unlock(&bios32lock);
99
100         VFLAG("bios32si: eax %ux\n", ci.eax);
101         if(ci.eax & 0xff)
102                 return nil;
103         VFLAG("bios32si: base %#ux length %#ux offset %#ux\n",
104                 ci.ebx, ci.ecx, ci.edx);
105
106         if((si = malloc(sizeof(BIOS32si))) == nil)
107                 return nil;
108         if((si->base = vmap(ci.ebx, ci.ecx)) == nil){
109                 free(si);
110                 return nil;
111         }
112         si->length = ci.ecx;
113
114         ptr = UPTR2INT(si->base)+ci.edx;
115         si->ptr[0] = ptr & 0xffff;
116         si->ptr[1] = (ptr>>16) & 0xffff;
117         si->ptr[2] = KESEL;
118         VFLAG("bios32si: eax entry %ux\n", ptr);
119
120         return si;
121 }