home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / mac / MAC / Programming Stuff / Macintosh Debugging / Blat / blat.a < prev    next >
Encoding:
Text File  |  1992-08-07  |  26.3 KB  |  607 lines  |  [TEXT/MPS ]

  1. ; Blat:
  2. ;    To fool around with the MMU registers and tables.  
  3. ;
  4. ;    Copyright © 1991 by Apple Computer, Inc., all rights reserved.
  5. ;
  6. ;    by     Bo3b Johnson        8/28/91
  7. ;            MS 37-DS
  8. ;    for best viewing, use Palatino 12.
  9. ;
  10. ;     Found out you can't do PMOVE to a data register on 030.  Weak.
  11.  
  12. ; Questions:
  13. ;    If I don't go VBR based, then I must know something about Macsbug and where it is
  14. ;        calling from.  The problem is that I bust the Macsbug bus error stuffing, and then call
  15. ;        DebugStr, which leads to wedge-city.  If VBR based, then Macsbug stuff there, for most,
  16. ;         but seems to have something else that causes it to freak out.
  17. ;        -- turns out to have been Macsbug calling the video driver to switch modes, and
  18. ;         that code installed a bus error handler. 
  19. ;    Do I need to flush the Data cache for the cpu though?  ie, does the MMU skip the data
  20. ;        cache and get something stale from memory when it might be unprotected?
  21. ;    Maybe have a recover routine that turns off the mapping by putting it back to the 
  22. ;        system start way?  
  23. ;    Maybe only emulate the access for things that are being ignored?  eg. if it is an error,
  24. ;        I can show it and not let it happen. 
  25. ;    Totally rad bug: copy/paste error of having an extra page mapped to the same place in
  26. ;        RAM, in the system heap.  When that page got used, I died.  Very hard to find.
  27. ;        Worse, I did it twice.  Had another several bugs in table over 8 Meg. 
  28.  
  29. ;*** make the data access into a function instead, have pascal routine fill it.  Access method.
  30.  
  31.     INCLUDE    'ToolEqu.a'
  32.     INCLUDE    'Traps.a'
  33.     INCLUDE    'PackMacs.a'
  34.     INCLUDE    'QuickEqu.a'
  35.     INCLUDE    'SysEqu.a'
  36.     
  37.     
  38.     MACHINE    MC68030
  39.  
  40. ;-------------------------------------------------------------------------------------------------------------------------
  41.  
  42.     
  43. ;--------------------------------------------------------------------------------------------------------------------
  44. ; These tables are exported so that the Pascal can get to the tables as just a chunk of data.
  45. ; Since I can't really just access them as pointers, I have these access methods to export the
  46. ; pointer to the Pascal.  This makes the Pascal easier to read, with less coercion.   These
  47. ; glue routines just return the address of each of the tables I use.   Pascal and assembly
  48. ; don't talk to each other totally smoothly.
  49. ; Each routine is of the form:
  50. ;    FUNCTION Getxxx: Ptr;
  51.  
  52. AccessMethods    PROC                    ; so it's in a proc for assembler. 
  53.  
  54.         EXPORT    GetStartSpace, GetEndOfTables
  55.         EXPORT    GetFirstLevel32, GetSecondLevel32, GetThirdLevel32, GetFourthLevel32
  56.         EXPORT    GetFirstLevel24, GetSecondLevel24
  57.  
  58. GetStartSpace
  59.     LEA        StartSpace, A0                    ; address of table.
  60.     MOVE.L    A0, 4(A7)                        ; replace function result.
  61.     RTS                                        ; and return it.
  62.     
  63. GetEndOfTables
  64.     LEA        EndOfTables, A0                    ; address of table.
  65.     MOVE.L    A0, 4(A7)                        ; replace function result.
  66.     RTS                                        ; and return it.
  67.         
  68. GetFirstLevel32
  69.     LEA        FirstLevel32, A0                    ; address of table.
  70.     MOVE.L    A0, 4(A7)                        ; replace function result.
  71.     RTS                                        ; and return it.
  72.     
  73. GetSecondLevel32
  74.     LEA        SecondLevel32, A0                ; address of table.
  75.     MOVE.L    A0, 4(A7)                        ; replace function result.
  76.     RTS                                        ; and return it.
  77.     
  78. GetThirdLevel32
  79.     LEA        ThirdLevel32, A0                ; address of table.
  80.     MOVE.L    A0, 4(A7)                        ; replace function result.
  81.     RTS                                        ; and return it.
  82.     
  83. GetFourthLevel32
  84.     LEA        FourthLevel32, A0                ; address of table.
  85.     MOVE.L    A0, 4(A7)                        ; replace function result.
  86.     RTS                                        ; and return it.
  87.  
  88.  
  89. GetFirstLevel24
  90.     LEA        FirstLevel24, A0                    ; address of table.
  91.     MOVE.L    A0, 4(A7)                        ; replace function result.
  92.     RTS                                        ; and return it.
  93.     
  94. GetSecondLevel24
  95.     LEA        SecondLevel24, A0                ; address of table.
  96.     MOVE.L    A0, 4(A7)                        ; replace function result.
  97.     RTS                                        ; and return it.
  98.             
  99.     
  100. ;-------------------------------------------------------------------------------------------------------------------------
  101. ; Now a routine to install the VBR vector passed in as the current VBR vector.  This is
  102. ; just an access method for the Pascal code to set the VBR register.  Could be INLINE, but
  103. ; since I have an assembly file anyway, I might as well make it clear.
  104. ;     PROCEDURE SetVBR (vbrPointer: Ptr);
  105.  
  106.     EXPORT    SetVBR
  107.     
  108. SetVBR
  109.     MOVE.L    (SP)+, A0                        ; return address
  110.     MOVE.L    (SP)+, A1                        ; move pointer into register,
  111.     MOVEC        A1, VBR                        ; move pointer into VBR register.
  112.     JMP        (A0)                            ; and return to caller.
  113.     
  114.     
  115. ; A function to send back a value, the VBR register value currently in use.
  116. ; This is the counterpart of SetVBR naturally.  
  117. ;     FUNCTION GetVBR: LongInt;
  118.  
  119.     EXPORT    GetVBR
  120.     
  121. GetVBR
  122.     MOVEC        VBR, A0                        ; can only move into register.
  123.     MOVE.L    A0, 4(SP)                        ; move it to function result. 
  124.     RTS                                        ; and return.
  125.     
  126. ;-------------------------------------------------------------------------------------------------------------------------
  127. ; When switching to my MMU tables, I need to do the switch without turning off the MMU.
  128. ; The trouble is that on an IIci, Ram Bank B physically starts at $400 0000, and is mapped
  129. ; to zero.  If I turn off the MMU at any time, the banks flip flop out to physical space, and
  130. ; I get wedge city because the CPU is left stranded in some bogus place.
  131. ; This routine does what SwapMMUMode does on those machines, by making the switch
  132. ; without turning off the MMU.
  133. ;     PROCEDURE SetMMURegisters (theRegisters: MMURegisters);
  134.  
  135. MMURegisters    RECORD    0
  136. theCRP            DS.L        2                    ; Int64Bit in Pascal.  Double Long.
  137. theTC            DS.L        1
  138.                 ENDR
  139.                 
  140.     EXPORT    SetMMURegisters
  141.     
  142. SetMMURegisters
  143.     BSR.S        TurnInterruptsOff                ; be sure nothing else is running.
  144.     
  145.      WITH        MMURegisters
  146.     
  147.     MOVE.L    4(SP), A0                        ; fetch 'theRegisters' pointer.
  148.     PLOADR    #5, theCRP(A0)                    ; #5 is User Data Space function code.
  149.     PMOVEFD    theCRP(A0), CRP                ; don't flush ATC, load with new set.
  150.     PMOVE        theTC(A0), TC                    ; This flushes ATC, sets new TC.
  151.     
  152.     BSR.S        TurnInterruptsOn
  153.     
  154.     MOVE.L    (SP)+, (SP)                        ; crush input with return address
  155.     RTS                                        ; and exit.
  156.     
  157.     
  158. ;-------------------------------------------------------------------------------------------------------------------------
  159. ; This routine is to allow an interface to the PTEST instruction.  The instruction allows me
  160. ; to take an address passed in, and find out what entry in my MMU tables correspond to it.
  161. ; This is handy, so I don't have to do a bunch of weird code to find an address.  The Ptr
  162. ; passed back is the pointer returned from PTEST as the MMU entry that matches.  The
  163. ; #5 is the address space, as the Supervisor Data Space, which is where the VBR is located,
  164. ; the #7 means to use the full tables, and skip the ATC, and the result is stored in A1.
  165. ;     FUNCTION FindMMUEntry (address: Ptr): Ptr;
  166.  
  167.     EXPORT    FindMMUEntry
  168.     
  169. FindMMUEntry
  170.     MOVE.L    4(SP), A0                        ; address to find entry for,
  171.     PTESTW    #5, (A0), #7, A1                    ; use the tables, not the ATC to test.
  172.     MOVE.L    (SP)+, A0                        ; return address
  173.     ADDQ        #4, SP                            ; kill input parameter,
  174.     MOVE.L    A1, (SP)                            ; save result as function result.
  175.     JMP        (A0)                            ; and return.
  176.     
  177.     
  178. ;-------------------------------------------------------------------------------------------------------------------------
  179. ; An access method to allow for saving the A5 register as a PC-Relative variable.
  180. ; This is so that it is handy when called as part of a bus error.
  181. ; This can only be called during the time when A5 is expected to be valid.
  182.  
  183.     EXPORT    SaveTheA5
  184.  
  185. SaveTheA5
  186.     LEA        dcmdA5(PC), A0                    ; the variable being saved,
  187.     MOVE.L    A5, (A0)                            ; set to the current A5.
  188.     RTS
  189.     
  190. dcmdA5        DC.L    0                        ; PC Relative addressed storage.
  191.  
  192.  
  193. ;-------------------------------------------------------------------------------------------------------------------------
  194. ; A small method to flush the Address Translation Cache in the MMU.  The ATC is
  195. ; invalid after I change the protection bits for the 0 page, since the WriteProtect bit is
  196. ; saved in the ATC line.  This takes the input pointer as the place to be flushed.  This
  197. ; is so I can just flush the individual line in the cache that needs it, rather than doing
  198. ; the brute force flush them all, that I was doing before.  The PFLUSH on #0, #0 says
  199. ; to use the mask as 0, so that it will flush all address spaces as any function code.  Since
  200. ; I only protect memory from 0..255, and that is a single line in the ATC, I just set the
  201. ; destination to 0, and flush that single page.  
  202. ;    PROCEDURE FlushATC (address: Ptr);
  203.  
  204.     EXPORT    FlushATC
  205.     
  206. FlushATC
  207.     MOVE.L    4(SP), A0                        ; set up the cache line from input.
  208.     PFLUSH    #0, #0, (A0)                        ; flush just that line in all function codes.
  209.     MOVE.L    (SP)+, (SP)                        ; crush input parameter.
  210.     RTS
  211.  
  212. ;-------------------------------------------------------------------------------------------------------------------------
  213. ; This will just turn them off in a reasonable fashion.  It will save off the value in the SR
  214. ; in a A5-relative storage, for later use turning them on.  This saves the mask from being
  215. ; set to something weird, since I'm not sure the state of the machine when this might
  216. ; get called.  This naturally requires that A5 be set up before it is used.
  217. ;     PROCEDURE TurnInterruptsOff;
  218.  
  219.     EXPORT    TurnInterruptsOff
  220.     IMPORT    gSavedSR: DATA
  221.     
  222. TurnInterruptsOff
  223.     MOVE        SR, gSavedSR(A5)                ; save the current value
  224.     ORI            #$0700, SR                        ; turn off all interrupts.
  225.     RTS                                        ; and exit.
  226.  
  227.  
  228. ; This turns them back on, but does so by using the A5-relative pSavedSR.  If that's not
  229. ; valid, then this will be bad.
  230. ;     PROCEDURE TurnInterruptsOn;
  231.  
  232.     EXPORT    TurnInterruptsOn
  233.     
  234. TurnInterruptsOn
  235.     MOVE        gSavedSR(A5), SR                ; stuff it back into the SR, restoring interrupts.
  236.     RTS
  237.  
  238.  
  239. ;-------------------------------------------------------------------------------------------------------------------------
  240. ; This bus error hander is the one that gets installed as part of turning it on.  Rather than
  241. ; have some big assembly language goop here, this will just do the minimum it needs to
  242. ; glue in the Pascal handler, then jump to that handler instead. 
  243. ; The first thing it needs to do is save the registers that Pascal will crush, since a bus error
  244. ; handler has to save all registers.
  245. ; It also turns off interrupts in here, since I will be moving MMU tables around, which
  246. ; could cause an interrupt routine to crash.
  247. ; It sets up A5 to be the dcmd's A5 world, so that the Pascal can use globals. 
  248. ; It will pass the pointer to the stack frame, so that the Pascal can use that record to decide
  249. ; what to do.
  250. ; It will return by an RTE in order to restart the CPU where it left off, and will dispose of
  251. ; the exception stack frame.  This is hard to do from Pascal too.  The RTE will reload the
  252. ; SR with the right interrupt mask too, so I don't save it's contents.
  253. ; It isn't possible to set a breakpoint or debugger statement in this routine, since this will
  254. ; be called when a protection violation occurs.  That happens when Macsbug tries to set it's
  255. ; vector, and when Macsbug switches video states, the video driver installs a bus error
  256. ; handler.  If Macsbug is invoked while it is already running, you get an infinite loop.
  257. ; Added the PTEST to this glue area, since it had to be in assembly anyway.  This tests to
  258. ; see if the bus error is MMU related or not, and if it isn't, it just jumps on to the standard
  259. ; bus error handler in 8; under the assumption that that would be what the system does
  260. ; in the standard (no blat) case.
  261. ; The PTEST is kind of complicated.  I'm using DFC since that should always be right when
  262. ; I have a bus error, as the destination address space, either program or data, and in
  263. ; supervisor or user mode, where I don't want to have to check.  The $10(A7) crap is 
  264. ; to take the value at A7+$10, an address pointing to the fault address, and to then (A0)
  265. ; it to get the actual address that faulted.  That address is the one I need to see if it is
  266. ; bogus, or merely an MMU fault.  The #7 says to drive the MMU tables to full depth to
  267. ; see if it can find the fault address in the table.   Further info found via experiments:
  268. ; The bus error bit in the MMUSR is not set when a bad address like -4 is referenced.  The
  269. ; docs are vague, but seems to only be set if the table tree itself caused a bus error.  In the
  270. ; ATC only case (#0) it was also not set, so I'm not sure how an address would get that
  271. ; set in the ATC.  Turning the logic upside down, I'll look for a WP bit or an Invalid bit
  272. ; in the MMUSR and if both those are missing, then I'll assume it was a stock bus error
  273. ; and feed it on through.  The Invalid bit is set if the DT=0, as I set when read protection
  274. ; is desired.  I used to assume everything was an MMU fault, and try to find the ones
  275. ; that weren't.  That didn't work, so now I assume everything is a regular bus error, and
  276. ; look for MMU faults.  I thought you'd like to know some of the reasons why the 
  277. ; logic is this way, not just see the logic.
  278.  
  279. registerSize        EQU    15*4                    ; saved register set on stack. 
  280.  
  281.     EXPORT    BusErrorGlue
  282.     IMPORT    BusError
  283.     IMPORT    gStandardBusError : DATA
  284.     IMPORT    gStandardVBRBusError : DATA
  285.     
  286. BusErrorGlue
  287.     MOVEM.L    A0-A6/D0-D7, -(SP)                ; save all registers to be conservative.
  288.     
  289.     MOVE.L    $10+registerSize(A7), A0            ; get the fault address.
  290.     MOVE.W    $A+registerSize(A7), D0            ; get SSW from frame.
  291.     MOVEC        D0, DFC                            ; stuff it into DFC for PTEST.
  292.     PTESTW    DFC, (A0), #7                    ; use the tables, not the ATC to test.
  293.     
  294.     CLR.W        -(A7)                            ; make space for lame MMU
  295.     PMOVE        MMUSR, (A7)                    ; get the result of the search. 
  296.     MOVE.W    (A7)+, D0                        ; get MMUSR, from only addressing mode.
  297.     ANDI.W    #$0C00, D0                        ; test WP and Invalid bits.
  298.     BEQ.S        StandardBusError                ; if neither bit set, it's a normal bus error.
  299.     
  300. ; If the bit wasn't set, that means it was MMU related, and the Pascal handler gets it.
  301.  
  302.     ORI.W        #$0700, SR                        ; Turn interrupts off.
  303.     
  304.     MOVE.L    dcmdA5(PC), A5                    ; set up A5.
  305.     
  306.     PEA        registerSize(SP)                    ; push pointer to stack frame,
  307.     JSR            BusError                        ; go handle it.
  308.     
  309.     MOVEM.L    (SP)+, A0-A6/D0-D7                ; restore registers.
  310.     RTE                                        ; restores the SR too.
  311.  
  312.  
  313. ; This is where I send the PC off to the previously installed bus error handler, since it 
  314. ; wasn't MMU related.  Restore the registers, then vector off to the old handler since it
  315. ; is presumably primed to handle this error.  It will RTE out, so this is a JMP (as RTS).
  316. ; Decide which bus error handler to send it to, by checking the gStandardVBRBusError
  317. ; first, and if it is not equal to the BusErrorGlue, it is a valid handler, that takes precedence
  318. ; over the one in low memory.  If not, use the one from low memory, saved in the
  319. ; gStandardBusError variable.
  320. ; *** skip use of global, if use 8 anyway.
  321.  
  322. StandardBusError
  323.     MOVE.L    dcmdA5(PC), A5                    ; set up A5.
  324.     LEA        oldBusError, A0                    ; set var to it.
  325.     
  326.     MOVE.L    gStandardVBRBusError(A5), (A0)    ; assume it will work,
  327.     LEA        BusErrorGlue, A1                ; if me, can't use it.
  328.     CMP.L        gStandardVBRBusError(A5), A1    ; address of potential handler,
  329.     BNE.S        @0                                ; if no match, use it.
  330.     
  331.     MOVE.L    gStandardBusError(A5), (A0)        ; address of prior handler,
  332.     
  333. @0
  334.     MOVEM.L    (SP)+, A0-A6/D0-D7                ; restore registers.
  335.     MOVE.L    oldBusError (PC), -(A7)            ; address of prior handler,
  336.     RTS                                        ; jump to it.
  337.     
  338. oldBusError        DC.L    0                        ; pc relative.
  339.  
  340.  
  341. ;-------------------------------------------------------------------------------------------------------------------------
  342. ;--------------------------------------------------------------------------------------------------------------------
  343. ; The first level table is pointed to by the CRP register, and is used to map the entire
  344. ; 32-bit address space.  The slot and I/O space are set with Cache Inhibit, so they get an
  345. ; immediate write instead of being cached.  The invalid pages are DT=0.
  346. ; In the real system tables, the RAM above 08000000 is set as invalid, probably to force
  347. ; a bus error earlier.  Unfortunately, I need to know if it is a real bus error or mmu
  348. ; induced, so I mark them as valid, then let the memory subsystem return a bus error
  349. ; for no ram installed.  Thank you, microsoft word for an easy to find real bus error that
  350. ; pointed out this flaw when I had them marked DT=0.
  351. ; This is in use, and it is 5 bits worth of 32-bit address space.  5 bits of the space is thus
  352. ; 32 entries, dividing the 4 gig space into 32 hunks.  128 Meg per hunk.
  353. ; This is so that the superslot address spaces are all distinct.
  354. ; The DT=01 means early termination, so all pages are valid.
  355. ; The StartSpace here is so that I can move the tables around in the dcmd space, and just
  356. ; have the tables there, instead of in the system heap.  The tables have to be quad-long word
  357. ; aligned though, so the starting 16 bytes of zeros is to allow me to move the tables from
  358. ; FirstLevel to EndTables further up in memory to make the starting address for FirstLevel
  359. ; quad-long word aligned.  Hey, it's an MMU requirement, not my plan.  During the Init,
  360. ; I BlockMove the table up to the right spot so that the low nibble will be zero.
  361.  
  362. StartSpace        DC.L    0, 0, 0, 0                    ; to allow for quad-long aligned tables.
  363.                 
  364. ; *** could be a bit cleaner if I use a label here, like FirstTableData so that the init stuff
  365. ;    doesn't have to presume FirstLevel32 is the actual first data.
  366. FirstLevel32        DC.L    $00000001, $08000001        ; a 128 Meg chunk for each.
  367.                 DC.L    $10000001, $18000001        ; all invalid space, DT=0 for invalid.
  368.                 DC.L    $20000001, $28000001
  369.                 DC.L    $30000001, $38000001
  370.                 DC.L    $40000001, $48000001        ; rom space here, so valid.
  371.                 DC.L    $50000041, $58000041        ; Cache Inhibit bit too, slot and I/O space.
  372.                 DC.L    $60000041, $68000041
  373.                 DC.L    $70000041, $78000041
  374.                 DC.L    $80000041, $88000041
  375.                 DC.L    $90000041, $98000041
  376.                 DC.L    $A0000041, $A8000041
  377.                 DC.L    $B0000041, $B8000041
  378.                 DC.L    $C0000041, $C8000041
  379.                 DC.L    $D0000041, $D8000041
  380.                 DC.L    $E0000041, $E8000041
  381.                 DC.L    $F0000041, $F8000041        ; Full 32-bit address space.
  382.                 
  383.                 
  384. ;  This is the second level table, of the MMU tree, and it is pointed at by the first entry
  385. ; in the first level table.  That is the first 128 Meg space, and this divides that space up 
  386. ; using the 7 bits for TIB.  7 bits means 128 entries, so each piece is thus 1 Meg in size.
  387. ; Since this part of the address space is always in RAM, I don't have to worry about
  388. ; the cache inhibit bit, or invalid pages.
  389.  
  390. SecondLevel32    DC.L    $00000001, $00100001, $00200001, $00300001
  391.                 DC.L    $00400001, $00500001, $00600001, $00700001
  392.                 DC.L    $00800001, $00900001, $00A00001, $00B00001
  393.                 DC.L    $00C00001, $00D00001, $00E00001, $00F00001
  394.                 
  395.                 DC.L    $01000001, $01100001, $01200001, $01300001
  396.                 DC.L    $01400001, $01500001, $01600001, $01700001
  397.                 DC.L    $01800001, $01900001, $01A00001, $01B00001
  398.                 DC.L    $01C00001, $01D00001, $01E00001, $01F00001
  399.                 
  400.                 DC.L    $02000001, $02100001, $02200001, $02300001
  401.                 DC.L    $02400001, $02500001, $02600001, $02700001
  402.                 DC.L    $02800001, $02900001, $02A00001, $02B00001
  403.                 DC.L    $02C00001, $02D00001, $02E00001, $02F00001
  404.                 
  405.                 DC.L    $03000001, $03100001, $03200001, $03300001
  406.                 DC.L    $03400001, $03500001, $03600001, $03700001
  407.                 DC.L    $03800001, $03900001, $03A00001, $03B00001
  408.                 DC.L    $03C00001, $03D00001, $03E00001, $03F00001
  409.                 
  410.                 DC.L    $04000001, $04100001, $04200001, $04300001
  411.                 DC.L    $04400001, $04500001, $04600001, $04700001
  412.                 DC.L    $04800001, $04900001, $04A00001, $04B00001
  413.                 DC.L    $04C00001, $04D00001, $04E00001, $04F00001
  414.                 
  415.                 DC.L    $05000001, $05100001, $05200001, $05300001
  416.                 DC.L    $05400001, $05500001, $05600001, $05700001
  417.                 DC.L    $05800001, $05900001, $05A00001, $05B00001
  418.                 DC.L    $05C00001, $05D00001, $05E00001, $05F00001
  419.                 
  420.                 DC.L    $06000001, $06100001, $06200001, $06300001
  421.                 DC.L    $06400001, $06500001, $06600001, $06700001
  422.                 DC.L    $06800001, $06900001, $06A00001, $06B00001
  423.                 DC.L    $06C00001, $06D00001, $06E00001, $06F00001
  424.                 
  425.                 DC.L    $07000001, $07100001, $07200001, $07300001
  426.                 DC.L    $07400001, $07500001, $07600001, $07700001
  427.                 DC.L    $07800001, $07900001, $07A00001, $07B00001
  428.                 DC.L    $07C00001, $07D00001, $07E00001, $07F00001
  429.                 
  430.  
  431. ; This is when I replace that first entry with the pointer to this table, and change the
  432. ; DT=2 so that it indicates the next level will have short format descriptors.
  433. ; Like:
  434. ;                DC.L    $xxxx xx02
  435. ; Where I stuff the xxx bits with the address of the new table entry.
  436.  
  437. ; Third level table, when installed for the first entry of the second4 level table. 
  438. ; This table, breaks up the first 1 Meg of the system into 16, 64-K hunks.  I map all of the
  439. ; pages as contiguous memory, and thus these are early termination descriptors too.  The
  440. ; only exception is the first 64K hunk, which points to another table.
  441. ; The tables are set up this way, with the 5748 for no particular reason, except that the
  442. ; prototype I had built had a couple of tables already, and this made it so I didn't have to
  443. ; build all new ones.  There doesn't seem to be an advantage to different ways of specifying
  444. ; it, since all bits of an address have to be mapped.
  445.                 
  446. ThirdLevel32    DC.L    $00000001    ; 02 for real.
  447.                 DC.L    $00010001    ; 64-K boundary, early termination.
  448.                 DC.L    $00020001
  449.                 DC.L    $00030001
  450.                 DC.L    $00040001
  451.                 DC.L    $00050001
  452.                 DC.L    $00060001
  453.                 DC.L    $00070001
  454.                 DC.L    $00080001
  455.                 DC.L    $00090001
  456.                 DC.L    $000A0001
  457.                 DC.L    $000B0001
  458.                 DC.L    $000C0001
  459.                 DC.L    $000D0001
  460.                 DC.L    $000E0001    ; 15
  461.                 DC.L    $000F0001    ; 16
  462.     
  463. ; For the 256 byte page sizes.  This table is big.  8 bits for this table, so 256 entries.
  464. ; At this fourth level, I am breaking up the first 64k hunk.  Breaking it into 256
  465. ; entries, gives 256 byte pages.
  466. ; Write protect the very first page, the 256 bytes of vectors.
  467. ; Read protect the 256 bytes, by setting it to DT=0 as invalid page.
  468. ; Turn off protection by setting DT=1.
  469. ; This table is used as the 4th level table for the 32-bit mode tables, and is used as the
  470. ; 3rd level table for 24-bit mode.  This is to save some work on maintaining the two
  471. ; sets of tables, since I can just use this lowest level in both cases.  This is especially 
  472. ; handy for setting and creating the VBR write protection.
  473.  
  474. FourthLevel32    DC.L    $00000001, $00000101, $00000201, $00000301
  475.                 DC.L    $00000401, $00000501, $00000601, $00000701
  476.                 DC.L    $00000801, $00000901, $00000A01, $00000B01
  477.                 DC.L    $00000C01, $00000D01, $00000E01, $00000F01
  478.                 
  479.                 DC.L    $00001001, $00001101, $00001201, $00001301
  480.                 DC.L    $00001401, $00001501, $00001601, $00001701
  481.                 DC.L    $00001801, $00001901, $00001A01, $00001B01
  482.                 DC.L    $00001C01, $00001D01, $00001E01, $00001F01
  483.                 
  484.                 DC.L    $00002001, $00002101, $00002201, $00002301
  485.                 DC.L    $00002401, $00002501, $00002601, $00002701
  486.                 DC.L    $00002801, $00002901, $00002A01, $00002B01
  487.                 DC.L    $00002C01, $00002D01, $00002E01, $00002F01
  488.  
  489.                 DC.L    $00003001, $00003101, $00003201, $00003301
  490.                 DC.L    $00003401, $00003501, $00003601, $00003701
  491.                 DC.L    $00003801, $00003901, $00003A01, $00003B01
  492.                 DC.L    $00003C01, $00003D01, $00003E01, $00003F01
  493.  
  494.                 DC.L    $00004001, $00004101, $00004201, $00004301
  495.                 DC.L    $00004401, $00004501, $00004601, $00004701
  496.                 DC.L    $00004801, $00004901, $00004A01, $00004B01
  497.                 DC.L    $00004C01, $00004D01, $00004E01, $00004F01
  498.  
  499.                 DC.L    $00005001, $00005101, $00005201, $00005301
  500.                 DC.L    $00005401, $00005501, $00005601, $00005701
  501.                 DC.L    $00005801, $00005901, $00005A01, $00005B01
  502.                 DC.L    $00005C01, $00005D01, $00005E01, $00005F01
  503.                 
  504.                 DC.L    $00006001, $00006101, $00006201, $00006301
  505.                 DC.L    $00006401, $00006501, $00006601, $00006701
  506.                 DC.L    $00006801, $00006901, $00006A01, $00006B01
  507.                 DC.L    $00006C01, $00006D01, $00006E01, $00006F01
  508.                 
  509.                 DC.L    $00007001, $00007101, $00007201, $00007301
  510.                 DC.L    $00007401, $00007501, $00007601, $00007701
  511.                 DC.L    $00007801, $00007901, $00007A01, $00007B01
  512.                 DC.L    $00007C01, $00007D01, $00007E01, $00007F01
  513.                 
  514.                 DC.L    $00008001, $00008101, $00008201, $00008301
  515.                 DC.L    $00008401, $00008501, $00008601, $00008701
  516.                 DC.L    $00008801, $00008901, $00008A01, $00008B01
  517.                 DC.L    $00008C01, $00008D01, $00008E01, $00008F01
  518.                 
  519.                 DC.L    $00009001, $00009101, $00009201, $00009301
  520.                 DC.L    $00009401, $00009501, $00009601, $00009701
  521.                 DC.L    $00009801, $00009901, $00009A01, $00009B01
  522.                 DC.L    $00009C01, $00009D01, $00009E01, $00009F01
  523.                 
  524.                 DC.L    $0000A001, $0000A101, $0000A201, $0000A301
  525.                 DC.L    $0000A401, $0000A501, $0000A601, $0000A701
  526.                 DC.L    $0000A801, $0000A901, $0000AA01, $0000AB01
  527.                 DC.L    $0000AC01, $0000AD01, $0000AE01, $0000AF01
  528.                 
  529.                 DC.L    $0000B001, $0000B101, $0000B201, $0000B301
  530.                 DC.L    $0000B401, $0000B501, $0000B601, $0000B701
  531.                 DC.L    $0000B801, $0000B901, $0000BA01, $0000BB01
  532.                 DC.L    $0000BC01, $0000BD01, $0000BE01, $0000BF01
  533.                 
  534.                 DC.L    $0000C001, $0000C101, $0000C201, $0000C301
  535.                 DC.L    $0000C401, $0000C501, $0000C601, $0000C701
  536.                 DC.L    $0000C801, $0000C901, $0000CA01, $0000CB01
  537.                 DC.L    $0000CC01, $0000CD01, $0000CE01, $0000CF01
  538.                 
  539.                 DC.L    $0000D001, $0000D101, $0000D201, $0000D301
  540.                 DC.L    $0000D401, $0000D501, $0000D601, $0000D701
  541.                 DC.L    $0000D801, $0000D901, $0000DA01, $0000DB01
  542.                 DC.L    $0000DC01, $0000DD01, $0000DE01, $0000DF01
  543.                 
  544.                 DC.L    $0000E001, $0000E101, $0000E201, $0000E301
  545.                 DC.L    $0000E401, $0000E501, $0000E601, $0000E701
  546.                 DC.L    $0000E801, $0000E901, $0000EA01, $0000EB01
  547.                 DC.L    $0000EC01, $0000ED01, $0000EE01, $0000EF01
  548.                 
  549.                 DC.L    $0000F001, $0000F101, $0000F201, $0000F301
  550.                 DC.L    $0000F401, $0000F501, $0000F601, $0000F701
  551.                 DC.L    $0000F801, $0000F901, $0000FA01, $0000FB01
  552.                 DC.L    $0000FC01, $0000FD01, $0000FE01, $0000FF01
  553.                 
  554.  
  555. ; And in 24 bit mode, I need to have a different set of tables.
  556. ; This one starts out as the 16 megabyte actual space, since the top 8 bits are thrown out.
  557. ; With 4 bits for the first level, I have 16 entries, so each entry is for 1 meg.
  558. ; The levels are mapped to other spaces like it says in the Guide to Macintosh Hardware.
  559.  
  560. FirstLevel24        DC.L    $00000001    ; top=0
  561.                 DC.L    $00100001    ; top=1,  1 meg boundary.
  562.                 DC.L    $00200001    ; top=2
  563.                 DC.L    $00300001    ; top=3
  564.                 DC.L    $00400001    ; top=4
  565.                 DC.L    $00500001    ; top=5
  566.                 DC.L    $00600001    ; top=6
  567.                 DC.L    $00700001    ; top=7
  568.                 DC.L    $40800001    ; top=8,   for ROM at 8 meg.
  569.                 DC.L    $F9000041    ; slot 9 (mac)- CI bit on.
  570.                 DC.L    $FA000041    ; slot A - CI bit on.
  571.                 DC.L    $FB000041    ; top=B
  572.                 DC.L    $FC000041    ; top=C
  573.                 DC.L    $FD000041    ; top=D
  574.                 DC.L    $FE000041    ; top=E
  575.                 DC.L    $50000041    ; top=F,   i/o space, -CI bit on.
  576.  
  577. ; The next level is for the 4 bits of space next to be decoded by the MMU, so it is also a 
  578. ; 16 entry table.  This thus decodes the first 1 meg space into 64K hunks.
  579. ; The first entry in this table will point to the 4th level table used in 32-bit mode.
  580.  
  581. SecondLevel24    DC.L    $00000001
  582.                 DC.L    $00010001    ; 64k higher.
  583.                 DC.L    $00020001
  584.                 DC.L    $00030001
  585.                 DC.L    $00040001
  586.                 DC.L    $00050001
  587.                 DC.L    $00060001
  588.                 DC.L    $00070001
  589.                 DC.L    $00080001
  590.                 DC.L    $00090001
  591.                 DC.L    $000A0001
  592.                 DC.L    $000B0001
  593.                 DC.L    $000C0001
  594.                 DC.L    $000D0001
  595.                 DC.L    $000E0001
  596.                 DC.L    $000F0001
  597.  
  598. ; The third and final level for the 24-bit tables is the same as the 4th level for the 32-bit
  599. ; tables.  The second level table here just points to the same table above.
  600.  
  601. EndOfTables
  602.  
  603.     ENDPROC
  604.  
  605.     END
  606.     
  607.