1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         * Copyright (c) 1972 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         *********************************************************** */
 11 
 12 
 13 /* format: style4,delnl,insnl,tree,ifthenstmt,indnoniterend */
 14 
 15 get_main:
 16      procedure (Segp, Size, Tsdw);
 17 
 18 /* *      Subroutine to provide a wired, contiguous buffer/working segment for its caller.
 19    *      If this subroutine is called before paging is enabled (or at least before init_sst
 20    *      is called) the buffer/working segment will be allocated from the storage between
 21    *      the perm-wired segments and the paged segments. Otherwise pc_abs is called to
 22    *      find the necessary storage.
 23    *
 24    *      If the SLTE for the specified segment indicates it is paged, the storage is
 25    *      acquired fron that just below the paged segments, otherwise the storage
 26    *      just after the wired segments is used.
 27    *
 28    *      call get_main (Segp, size, Tsdw);
 29    *
 30    *      1. Segp          is a pointer to the segment wanted. (Input)
 31    *
 32    *      2. size          is the size of the segment wanted (in words)
 33    *                       The parameter is returned as the next higher 0 mod 1024 value. (Input/Ouput)
 34    *
 35    *      3. Tsdw          is a returned SDW for the segment. It is up to the caller to place
 36    *                       this SDW in the descriptor segment. (Output)
 37    *
 38    *      Last Modified (date and reason):
 39    *
 40    *      01/27/76, S. Webber (Initial coding)
 41    *      05/17/76, N. Morris for 28-5 compatibility
 42    *      11/08/80, W. Olin Sibert, to zero storage before returning
 43    August 1981      C. Hornig for new pc_abs.
 44    *      04/04/81, W. Olin Sibert, to use sdw_util
 45    *      September 1983, Keith Loepere, for paged wired segment.
 46 */
 47 
 48 dcl  Segp pointer parameter;
 49 dcl  Size fixed bin (18) parameter;
 50 dcl  Memory_address fixed bin (26) parameter;
 51 dcl  Tsdw fixed bin (71) parameter;
 52 
 53 dcl  cl fixed bin (9);
 54 dcl  code fixed bin (35);
 55 dcl  ptp ptr;
 56 dcl  astep ptr;
 57 dcl  segno fixed bin (18);
 58 dcl  save_sdw fixed bin (71);                               /* For keeping the SDW until we're done clearing the seg */
 59 dcl  memory_address fixed bin (26);
 60 dcl  page_no fixed bin;
 61 dcl  size fixed bin (18);
 62 dcl  size_mod_1024 fixed bin (18, -10);
 63 
 64 dcl  1 sdwi aligned like sdw_info automatic;
 65 
 66 dcl  dseg$ (0:1023) fixed bin (71) external static;
 67 dcl  int_unpaged_page_tables$ external static;
 68 dcl  slt$ fixed bin external static;
 69 dcl  unpaged_page_tables$ external static;
 70 
 71 dcl  absadr entry (ptr, fixed bin (35)) returns (fixed bin (26));
 72 dcl  make_sdw$unthreaded entry (fixed bin (18), fixed bin (71), ptr, ptr);
 73 dcl  ptw_util_$make_core entry (ptr, fixed bin (26));
 74 dcl  pc_abs$wire_abs_contig entry (ptr, fixed bin (9), fixed bin (9), fixed bin (35));
 75 dcl  privileged_mode_ut$swap_sdw entry (ptr, ptr);
 76 dcl  sdw_util_$construct entry (pointer, pointer);
 77 dcl  sdw_util_$set_access entry (pointer, bit (4) unaligned);
 78 dcl  syserr entry options (variable);
 79 dcl  syserr$error_code entry options (variable);
 80 
 81 dcl  (addr, addrel, baseno, bin, bit, divide, mod, null, string) builtin;
 82 ^L
 83 
 84           segno = bin (baseno (Segp), 18);
 85           sltp = addr (slt$);
 86           sltep = addr (slt.seg (segno));
 87 
 88           size_mod_1024 = fixed (Size + 1023, 18, -10);
 89           size = size_mod_1024;                             /* variables have different precisions */
 90 
 91           slte_uns.bit_count = size * 36;
 92           cl = divide (size_mod_1024, 1024, 18, 0);
 93           slte_uns.cur_length = cl;
 94 
 95           if slt.free_core_start = 0 then do;               /* must call pc_contig */
 96                call make_sdw$unthreaded (segno, Tsdw, astep, ptp);
 97                call pc_abs$wire_abs_contig (astep, 0, cl, code);
 98                if code ^= 0
 99                then
100 no_room:
101                     do;
102                          namep = addrel (slt.name_seg_ptr, slte.names_ptr);
103                          call syserr$error_code (CRASH, code, "get_main: Insufficient storage available for ^a",
104                               segnam.names (1).name);
105                     end;
106 
107                call privileged_mode_ut$swap_sdw (Segp, addr (Tsdw));
108                return;                                      /* All done for the after-init_sst case */
109                end;
110 
111 /* Check for no more room */
112 
113           if slt.free_core_size < size then do;
114                code = 0;
115                go to no_room;
116                end;
117 
118           if slte.paged
119           then memory_address = slt.free_core_start + slt.free_core_size - size;
120           else do;
121                memory_address = slt.free_core_start;
122                slt.free_core_start = slt.free_core_start + size;
123                end;
124           slt.free_core_size = slt.free_core_size - size;
125 
126 generate:
127           if slte.paged
128           then upt_ptr = addr (int_unpaged_page_tables$);             /* seg will get real page table when make_segs_paged is run */
129           else upt_ptr = addr (unpaged_page_tables$);
130 
131 /* Now fill in SDW */
132 
133           unspec (sdwi) = ""b;                              /* Prepare to call sdw_util to build the SDW */
134           string (sdwi.access) = "1010"b;                   /* Start out with RW access for clearing */
135           sdwi.size = size;                                 /* Segment is unpaged by default */
136 
137           sdwi.flags.paged = "1"b;
138           upt_entry_ptr = ptr (upt_ptr, upt.current_length);
139           upt.current_length = upt.current_length + 2 + round (cl, -1);
140           if upt.current_length > upt.max_length then do;
141                namep = addrel (slt.name_seg_ptr, slte.names_ptr);
142                call syserr (CRASH, "get_main: not enough room to allocate unpaged page table for ^a.", segnam.names (1).name);
143           end;
144           upt_entry.size = cl;
145           upt_entry.segno = segno;
146           do page_no = 1 to cl;
147                call ptw_util_$make_core (addr (upt_entry.ptws (page_no)), memory_address);
148                memory_address = memory_address + 1024;
149           end;
150 
151           sdwi.address = absadr (addr (upt_entry.ptws), (0));
152           call sdw_util_$construct (addr (Tsdw), addr (sdwi));
153                                                             /* Make an SDW */
154 
155           save_sdw = dseg$ (segno);                         /* Save the current SDW for this segment */
156           call privileged_mode_ut$swap_sdw (Segp, addr (Tsdw));
157                                                             /* and prepare to zero the segment */
158 
159 /* Even though memory is supposed to be clear, some of the "allocate-free"
160    tricks used for firmware may leave gruft around. */
161 
162           begin;
163 declare  segment_overlay (size) bit (36) aligned based (Segp);
164                segment_overlay = ""b;
165           end;
166 
167           call sdw_util_$set_access (addr (Tsdw), slte.access);
168                                                             /* Set the real access */
169 
170           call privileged_mode_ut$swap_sdw (Segp, addr (save_sdw));
171                                                             /* and replace it with what was there before */
172 
173           return;                                           /* Our caller will actually swap in the new SDW */
174                                                             /* when it is needed; some callers require both for a while */
175 %page;
176 given_address: entry (Segp, Memory_address, Size, Tsdw);
177 
178 /* Construct a memory segment as above, but use callers memory address. */
179 
180           segno = bin (baseno (Segp), 18);
181           sltp = addr (slt$);
182           sltep = addr (slt.seg (segno));
183 
184           size_mod_1024 = fixed (Size + 1023, 18, -10);
185           size = size_mod_1024;                             /* variables have different precisions */
186 
187           slte_uns.bit_count = size * 36;
188           cl = divide (size_mod_1024, 1024, 18, 0);
189           slte_uns.cur_length = cl;
190 
191           memory_address = Memory_address;
192           go to generate;
193 /* format: off */
194 %page; %include slt;
195 %page; %include slte;
196 %page; %include sdw_info;
197 %page; %include syserr_constants;
198 %page; %include unpaged_page_tables;
199 ^L
200 
201 /* BEGIN MESSAGE DOCUMENTATION
202 
203    Message:
204    get_main: insufficient storage available for NAME
205 
206    S:     $crash
207 
208    T:     $init
209 
210    M:     Insufficient wired memory
211    was available to create the segment NAME during initialization.
212    The system tape may be bad, or the configuration may be too small,
213    or the system parameters specified in the configuration deck may be
214    incorrect or inconsistent with the amount of main storage available.
215 
216    A:     $recover
217    Check the configuration and the CONFIG deck.
218    $boot_tape
219 
220    Message:
221    get_main: not enough room to allocate unpaged page table for NAME.
222 
223    S: $crash
224 
225    T: $init
226 
227    M: Either the segment unpaged_page_tables or int_unpaged_page_tables
228    was not big enough so as to have the page table for segment NAME allocated
229    within it.  The system tape may be bad, or changes made to the mst require
230    bigger unpaged page tables.
231 
232    A: $recover
233    Try another tape.  If bigger unpaged page tables are in order, a change
234    must be made to bootload_equs.incl.alm and collection 0 recompiled.
235    $boot_tape
236 
237    END MESSAGE DOCUMENTATION */
238 
239      end get_main;