ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/video_vosf.h
(Generate patch)

Comparing BasiliskII/src/Unix/video_vosf.h (file contents):
Revision 1.26 by cebix, 2001-07-06T20:49:48Z vs.
Revision 1.27 by gbeauche, 2001-07-07T09:14:47Z

# Line 35 | Line 35
35  
36   // Variables for Video on SEGV support
37   static uint8 *the_host_buffer;  // Host frame buffer in VOSF mode
38 static uint32 the_buffer_size;  // Size of allocated the_buffer
38  
39   struct ScreenPageInfo {
40      int top, bottom;                    // Mapping between this virtual page and Mac scanlines
41   };
42  
43   struct ScreenInfo {
45    uintptr memBase;                    // Real start address
44      uintptr memStart;                   // Start address aligned to page boundary
47    uintptr memEnd;                             // Address of one-past-the-end of the screen
45      uint32 memLength;                   // Length of the memory addressed by the screen pages
46      
47 <    uint32 pageSize;                    // Size of a page
47 >    uintptr pageSize;                   // Size of a page
48      int pageBits;                               // Shift count to get the page number
49      uint32 pageCount;                   // Number of pages allocated to the screen
50      
# Line 161 | Line 158 | static uint32 page_extend(uint32 size)
158  
159  
160   /*
161 < *  Initialize mainBuffer structure
161 > *  Initialize the VOSF system (mainBuffer structure, SIGSEGV handler)
162   */
163  
164 < static bool video_init_buffer(void)
164 > static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
165 >
166 > static bool video_vosf_init(void)
167   {
168 <        if (use_vosf) {
169 <                const uint32 page_size  = getpagesize();
170 <                const uint32 page_mask  = page_size - 1;
168 >        const uintptr page_size = getpagesize();
169 >        const uintptr page_mask = page_size - 1;
170 >        
171 >        // Round up frame buffer base to page boundary
172 >        mainBuffer.memStart = (((uintptr) the_buffer) + page_mask) & ~page_mask;
173 >        
174 >        // The frame buffer size shall already be aligned to page boundary (use page_extend)
175 >        mainBuffer.memLength = the_buffer_size;
176 >        
177 >        mainBuffer.pageSize = page_size;
178 >        mainBuffer.pageBits = log_base_2(mainBuffer.pageSize);
179 >        mainBuffer.pageCount =  (mainBuffer.memLength + page_mask)/mainBuffer.pageSize;
180 >        
181 >        // The "2" more bytes requested are a safety net to insure the
182 >        // loops in the update routines will terminate.
183 >        // See "How can we deal with array overrun conditions ?" hereunder for further details.
184 >        mainBuffer.dirtyPages = (char *) vm_acquire(mainBuffer.pageCount + 2);
185 >        if (mainBuffer.dirtyPages == VM_MAP_FAILED)
186 >                return false;
187                  
188 <                mainBuffer.memBase      = (uintptr) the_buffer;
189 <                // Round up frame buffer base to page boundary
190 <                mainBuffer.memStart             = (uintptr)((((unsigned long) the_buffer) + page_mask) & ~page_mask);
191 <                mainBuffer.memLength    = the_buffer_size;
192 <                mainBuffer.memEnd       = mainBuffer.memStart + mainBuffer.memLength;
193 <
194 <                mainBuffer.pageSize     = page_size;
195 <                mainBuffer.pageCount    = (mainBuffer.memLength + page_mask)/mainBuffer.pageSize;
196 <                mainBuffer.pageBits     = log_base_2(mainBuffer.pageSize);
197 <
198 <                if (mainBuffer.dirtyPages) {
199 <                        free(mainBuffer.dirtyPages);
200 <                        mainBuffer.dirtyPages = NULL;
201 <                }
202 <
203 <                mainBuffer.dirtyPages = (char *) malloc(mainBuffer.pageCount + 2);
204 <
205 <                if (mainBuffer.pageInfo) {
206 <                        free(mainBuffer.pageInfo);
207 <                        mainBuffer.pageInfo = NULL;
208 <                }
188 >        PFLAG_CLEAR_ALL;
189 >        PFLAG_CLEAR(mainBuffer.pageCount);
190 >        PFLAG_SET(mainBuffer.pageCount+1);
191 >        
192 >        // Allocate and fill in pageInfo with start and end (inclusive) row in number of bytes
193 >        mainBuffer.pageInfo = (ScreenPageInfo *) vm_acquire(mainBuffer.pageCount * sizeof(ScreenPageInfo));
194 >        if (mainBuffer.pageInfo == VM_MAP_FAILED)
195 >                return false;
196 >        
197 >        uint32 a = 0;
198 >        for (int i = 0; i < mainBuffer.pageCount; i++) {
199 >                int y1 = a / VideoMonitor.mode.bytes_per_row;
200 >                if (y1 >= VideoMonitor.mode.y)
201 >                        y1 = VideoMonitor.mode.y - 1;
202 >
203 >                int y2 = (a + mainBuffer.pageSize) / VideoMonitor.mode.bytes_per_row;
204 >                if (y2 >= VideoMonitor.mode.y)
205 >                        y2 = VideoMonitor.mode.y - 1;
206 >
207 >                mainBuffer.pageInfo[i].top = y1;
208 >                mainBuffer.pageInfo[i].bottom = y2;
209 >
210 >                a += mainBuffer.pageSize;
211 >                if (a > mainBuffer.memLength)
212 >                        a = mainBuffer.memLength;
213 >        }
214 >        
215 >        // We can now write-protect the frame buffer
216 >        if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
217 >                return false;
218 >        
219 >        // Initialize the handler for SIGSEGV
220 >        if (!sigsegv_install_handler(screen_fault_handler))
221 >                return false;
222 >        
223 >        // The frame buffer is sane, i.e. there is no write to it yet
224 >        mainBuffer.dirty = false;
225 >        return true;
226 > }
227  
195                mainBuffer.pageInfo = (ScreenPageInfo *) malloc(mainBuffer.pageCount * sizeof(ScreenPageInfo));
228  
229 <                if ((mainBuffer.dirtyPages == NULL) || (mainBuffer.pageInfo == NULL))
230 <                        return false;
231 <                
200 <                mainBuffer.dirty = false;
229 > /*
230 > * Deinitialize VOSF system
231 > */
232  
233 <                PFLAG_CLEAR_ALL;
234 <                // Safety net to insure the loops in the update routines will terminate
235 <                // See "How can we deal with array overrun conditions ?" hereunder for further details
236 <                PFLAG_CLEAR(mainBuffer.pageCount);
237 <                PFLAG_SET(mainBuffer.pageCount+1);
238 <
239 <                uint32 a = 0;
240 <                for (int i = 0; i < mainBuffer.pageCount; i++) {
241 <                        int y1 = a / VideoMonitor.mode.bytes_per_row;
211 <                        if (y1 >= VideoMonitor.mode.y)
212 <                                y1 = VideoMonitor.mode.y - 1;
213 <
214 <                        int y2 = (a + mainBuffer.pageSize) / VideoMonitor.mode.bytes_per_row;
215 <                        if (y2 >= VideoMonitor.mode.y)
216 <                                y2 = VideoMonitor.mode.y - 1;
217 <
218 <                        mainBuffer.pageInfo[i].top = y1;
219 <                        mainBuffer.pageInfo[i].bottom = y2;
220 <
221 <                        a += mainBuffer.pageSize;
222 <                        if (a > mainBuffer.memLength)
223 <                                a = mainBuffer.memLength;
224 <                }
225 <                
226 <                // We can now write-protect the frame buffer
227 <                if (vm_protect((char *)mainBuffer.memStart, mainBuffer.memLength, VM_PAGE_READ) != 0)
228 <                        return false;
233 > static void video_vosf_exit(void)
234 > {
235 >        if (mainBuffer.pageInfo != VM_MAP_FAILED) {
236 >                vm_release(mainBuffer.pageInfo, mainBuffer.pageCount * sizeof(ScreenPageInfo));
237 >                mainBuffer.pageInfo = (ScreenPageInfo *) VM_MAP_FAILED;
238 >        }
239 >        if (mainBuffer.dirtyPages != VM_MAP_FAILED) {
240 >                vm_release(mainBuffer.dirtyPages, mainBuffer.pageCount + 2);
241 >                mainBuffer.dirtyPages = (char *) VM_MAP_FAILED;
242          }
230        return true;
243   }
244  
245  
# Line 237 | Line 249 | static bool video_init_buffer(void)
249  
250   static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
251   {
252 < //      D(bug("screen_fault_handler: ADDR=0x%08X from IP=0x%08X\n", fault_address, fault_instruction));
252 > //      D(bug("screen_fault_handler: ADDR=%p from IP=%p\n", fault_address, fault_instruction));
253          const uintptr addr = (uintptr)fault_address;
254          
255          /* Someone attempted to write to the frame buffer. Make it writeable
256           * now so that the data could actually be written to. It will be made
257           * read-only back in one of the screen update_*() functions.
258           */
259 <        if ((addr >= mainBuffer.memStart) && (addr < mainBuffer.memEnd)) {
260 <                const int page  = (addr - mainBuffer.memStart) >> mainBuffer.pageBits;
249 <                caddr_t page_ad = (caddr_t)(addr & -mainBuffer.pageSize);
259 >        if (((uintptr)addr - mainBuffer.memStart) < mainBuffer.memLength) {
260 >                const int page  = ((uintptr)addr - mainBuffer.memStart) >> mainBuffer.pageBits;
261                  LOCK_VOSF;
262                  PFLAG_SET(page);
263 <                vm_protect((char *)page_ad, mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
263 >                vm_protect((char *)(addr & -mainBuffer.pageSize), mainBuffer.pageSize, VM_PAGE_READ | VM_PAGE_WRITE);
264                  mainBuffer.dirty = true;
265                  UNLOCK_VOSF;
266                  return true;
267          }
268          
269          /* Otherwise, we don't know how to handle the fault, let it crash */
270 <        fprintf(stderr, "do_handle_screen_fault: unhandled address 0x%08X", addr);
270 >        fprintf(stderr, "do_handle_screen_fault: unhandled address %p", fault_address);
271          if (fault_instruction != SIGSEGV_INVALID_PC)
272 <                fprintf(stderr, " [IP=0x%08X]", fault_instruction);
272 >                fprintf(stderr, " [IP=%p]", fault_instruction);
273          fprintf(stderr, "\n");
274   #if EMULATED_68K
275          uaecptr nextpc;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines