1 " ***********************************************************
  2 " *                                                         *
  3 " * Copyright, (C) Honeywell Bull Inc., 1987                *
  4 " *                                                         *
  5 " * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6 " *                                                         *
  7 " ***********************************************************
  8 
  9 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 10 "
 11 "         volmap_page
 12 "
 13 "         Routines to act on single pages of a volume map
 14 "
 15 "         Entries:
 16 "
 17 "             grap_volmap_page_unwired  - wires and reads in a volmap page
 18 "                                         deposits excess stock to volume map
 19 "
 20 "             write_volmap_page_unwired - writes and unwires a volmap page
 21 "
 22 "             start_async_read          - starts an asynchronous read cycle to
 23 "                                         the volume map
 24 "
 25 "             start_async_write         - starts an asynchronous write cycle to
 26 "                                         the volume map
 27 "
 28 "             post_io                   - posts a volume map i/o
 29 "
 30 "             poll_io                   - polls for complete volume map i/os
 31 "
 32 "         Written February 1982 by J. Bongiovanni
 33 "         Modified September 1982, J. Bongiovanni, not to do read on OS page
 34 "
 35 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 36 
 37           name      volmap_page
 38           segdef    grab_volmap_page_unwired
 39           segdef    write_volmap_page_unwired
 40           segdef    start_async_read
 41           segdef    start_async_write
 42           segdef    post_io
 43           segdef    poll_io
 44 
 45           link      volmap_abs_seg_link,volmap_abs_seg$
 46 
 47           even
 48 pc_wired_arg_list:
 49           vfd       18/6,18/4,36/0
 50 pread_arg_list:
 51           vfd       18/6,18/4,36/0
 52 pwrite_arg_list:
 53           vfd       18/4,18/4,36/0
 54 notify_arg_list:
 55           vfd       18/2,18/4,36/0
 56 
 57 one:      dec       1
 58 "^L
 59           include   aste
 60 "^L
 61           include   page_info
 62 "^L
 63           include   ptw
 64 "^L
 65           include   pvte
 66 "^L
 67           include   pxss_page_stack
 68 "^L
 69           include   stock_seg
 70 "^L
 71 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 72 "
 73 "         grab_volmap_page_unwired
 74 "
 75 "         call page$grab_volmap_page_unwired (pvtep, page_no, page_ptr)
 76 "
 77 "             pvtep = pointer to PVTE (Input)
 78 "             page_no = page number in volume map (Input)
 79 "             page_ptr = pointer to page in volume map (Output)
 80 "
 81 "         The volume map must be locked to this process with asynchronous
 82 "         state of idle. volmap_abs_seg must be set to refer to this volume
 83 "         map.
 84 "
 85 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 86 
 87 grab_volmap_page_unwired:
 88           push
 89           tsx6      page_fault$init_savex         " Recursive use of x7
 90 
 91           eppbp     ap|2,*                        " bp -> ptr -> PVTE
 92           eppbp     bp|0,*                        " bp -> PVTE
 93           tsx6      check_valid_call              " Check lock, async state, abs seg
 94 
 95           lprpab    bp|pvte.volmap_astep          " ab -> ASTE for volume map
 96           spriab    arg+8
 97           eppab     arg+8
 98           spriab    arg+2
 99           eppab     ap|4,*                        " Page number
100           spriab    arg+4
101           eppab     one                           " Number of pages
102           spriab    arg+6
103           ldaq      pc_wired_arg_list
104           staq      arg
105           call      pc_wired$wire_wait(arg)
106 
107           lda       ap|4,*                        " Page number
108           als       page_power                    " Offset in segment
109           eppab     volmap_abs_seg$0,al           " ab -> page
110           spriab    ap|6,*                        " Return to caller
111 
112           lprpbb    bp|pvte.volmap_stock_ptr      " bb -> record stock
113           lxl0      bb|record_stock.high_threshold " Above high threshold
114           cmpx0     bb|record_stock.n_free_in_stock
115           tpl       grab_volmap_returns           " No
116           epbpab    bb|0                          " ab -> base of stock_seg
117           eppab     ab|stock_seg.meters           " ab -> meters
118           aos       ab|rsmeters.high_thresh_detected
119           lda       ap|4,*                        " Page number
120           tsx7      volmap$deposit_to_volmap      " Deposit excess for this page
121 
122 grab_volmap_returns:
123           return
124 "^L
125 
126 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
127 "
128 "         write_volmap_page_unwired
129 "
130 "         call page$write_volmap_page_unwired (pvtep, page_no)
131 "
132 "             pvtep = pointer to PVTE (Input)
133 "             page_no = page number in volume map (Input)
134 "
135 "         The volume map must be locked to this process with asynchronous
136 "         state of idle. volmap_abs_seg must be set to refer to this volume
137 "         map.
138 "
139 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
140 
141 write_volmap_page_unwired:
142           push
143           eppbp     ap|2,*                        " bp -> ptr -> PVTE
144           eppbp     bp|0,*                        " bp -> PVTE
145           tsx6      check_valid_call              " Check lock, async state, abs-seg
146 
147           lprpab    bp|pvte.volmap_astep          " ab -> ASTE for volmap_seg
148           spriab    arg+8
149           eppab     arg+8
150           spriab    arg+2
151           eppab     ap|4,*                        " Page number
152           spriab    arg+4
153           eppab     one                           " One page
154           spriab    arg+6
155           ldaq      pc_wired_arg_list
156           staq      arg
157           call      pc_wired$unwire_write_wait(arg)
158 
159           return
160 "^L
161 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
162 "
163 "         start_async_read
164 "
165 "         tsx7      volmap_page$start_async_read
166 "         <return if page already in memory>
167 "         <return if page not in memory>
168 "
169 "         On entry,
170 "             bp -> PVTE
171 "             ab -> stock_seg.meters
172 "             Areg = page number in volume map
173 "             Volume map locked to this process, async state idle
174 "             PTL locked to this process
175 "
176 "         On exit,
177 "             Async state is Read
178 "
179 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
180 
181 start_async_read:
182           tsx6      page_fault$savex              " Recursive use of x7
183 
184           increment ab|rsmeters.async_read_calls
185 
186           sta       volmap_page_temp              " Page number
187 
188           lda       pds$processid                 " Check PTL
189           cmpa      sst$ptl
190           tnz       page_error$ptl_not_locked
191           cmpa      bp|pvte.volmap_lock           " Volmap lock held
192           tnz       page_error$volmap_page_invalid_call " No
193           ldx0      bp|pvte.volmap_async_state    " State idle
194           cmpx0     VOLMAP_ASYNC_IDLE,du
195           tnz       page_error$volmap_page_invalid_call  " No
196           lda       volmap_page_temp              " Page number
197           ana       -1,dl                         " Just to be sure
198           ora       VOLMAP_ASYNC_READ,du          " New async state
199           sta       bp|pvte.volmap_async_state
200 
201           lda       volmap_page_temp              " Page number
202           lprpap    bp|pvte.volmap_astep          " ap -> ASTE for volmap_seg
203           ldq       ap|aste_size,al               " PTW
204           canq      ptw.valid,dl                  " In memory
205           tnz       page_fault$unsavex            " Yes
206           canq      ptw.os,dl                     " I/O already in progress?
207           tnz       page_fault$unsavex_1          " Yes - should never happen
208 
209           increment ab|rsmeters.async_page_reads
210           increment sst$volmap_seg_page_faults
211           spriap    arg+8
212           eppap     arg+8
213           spriap    arg+2
214           eppap     volmap_page_temp              " Page number
215           spriap    arg+4
216           eppap     arg+10
217           spriap    arg+6
218           ldaq      pread_arg_list
219           staq      arg
220           call      page_fault$pread(arg)
221 
222           tsx7      post_io_pvtep                 " Check for screw case
223           tra       page_fault$unsavex_1
224 
225 "^L
226 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
227 "
228 "         start_async_write
229 "
230 "         tsx7      page_fault$start_async_write
231 "         <return if page is in memory>
232 "         <return if page in not in memory>
233 "
234 "         On entry,
235 "             bp -> PVTE
236 "             Volmap async state is Read
237 "             PTL locked to process
238 "
239 "         On exit,
240 "             Volmap async state is Write
241 "
242 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
243 
244 start_async_write:
245           tsx6      page_fault$savex              " Recursive use of x7
246 
247           sta       volmap_page_temp              " Page number
248           lda       pds$processid
249           cmpa      sst$ptl                       " PTL held
250           tnz       page_error$ptl_not_locked
251 
252           ldx0      bp|pvte.volmap_async_state
253           cmpx0     VOLMAP_ASYNC_READ,du
254           tnz       page_error$wrong_async_state
255 
256           lda       volmap_page_temp              " Page number
257           ana       -1,dl                         " Just in case
258           ora       VOLMAP_ASYNC_WRITE,du         " New state
259           sta       bp|pvte.volmap_async_state
260 
261           lda       volmap_page_temp              " Page number
262           lprpap    bp|pvte.volmap_astep          " ap -> ASTE for volmap_seg
263           ldq       ap|aste_size,al               " PTW
264           canq      ptw.valid,dl                  " In memory
265           tze       page_fault$unsavex_1          " No
266           canq      ptw.os,dl                     " Someone else writing it?
267           tnz       page_fault$unsavex            " Yes - skip call to pwrite
268 
269           spriap    arg+6                         " astep
270           eppap     arg+6
271           spriap    arg+2
272           eppap     volmap_page_temp              " Page number
273           spriap    arg+4
274           ldaq      pwrite_arg_list
275           staq      arg
276           call      page_fault$pwrite(arg)
277 
278           tsx7      post_io_pvtep                 " Check for screw case
279           tra       page_fault$unsavex
280 "^L
281 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
282 "
283 "         post_io
284 "
285 "         tsx7      volmap_page$post_io
286 "
287 "         On entry,
288 "             Areg = pvtx
289 "             PTL locked to process
290 "
291 "         post_io_pvtep - internal procedure, registers already setup
292 "
293 "         tsx7      post_io_pvtep
294 "
295 "         On entry,
296 "             bp -> PVTE
297 "             PTL locked to process
298 "
299 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
300 
301 
302 post_io:
303           eax0      0                             " Pvtx given
304           sta       volmap_page_temp              " pvtx
305           tra       post_io_join
306 
307 post_io_pvtep:
308           eax0      1                             " Pvtep given
309 
310 post_io_join:
311           read_clock
312           staq      post_io_start_time            " For metering
313 
314           eax0      0,x0                          " Pvtep given
315           tpnz      post_got_pvtep                " Yes
316           ldq       pvte_size,dl                  " Compute pvtep
317           mpy       volmap_page_temp              " Offset in array, one too high
318           eppbp     pvt$array
319           eppbp     bp|-pvte_size,ql              " bp -> PVTE
320 
321 post_got_pvtep:
322           lda       bp|pvte.volmap_async_state    " State in AU, page in AL
323           tra       post_io_state,au              " Do what's appropriate
324 post_io_state:
325           tra       0,x7                          " Idle
326           tra       post_read                     " Read
327           tra       post_write                    " Write
328 
329 post_read:
330           tsx6      page_fault$savex              " Recursive use of x7
331           lprpap    bp|pvte.volmap_astep          " ap -> ASTE for volmap_seg
332           ldq       ap|aste_size,al               " PTW
333           canq      ptw.er,dl                     " I/O Error
334           tze       post_read_noerr               " No
335           tsx7      io_error                      " Yes - handle
336           tra       post_idle                     " Set state to idle and notify
337 post_read_noerr:
338           canq      ptw.valid,dl                  " In memory
339           tnz       post_read_in_mem              " Yes
340           canq      ptw.os,dl                     " Did we lose the I/O?
341           tnz       page_fault$unsavex            " No
342           tra       post_idle                     " Yes, reset it..time will cure all
343 
344 post_read_in_mem:
345           ana       -1,dl                         " Page number
346           lprpbb    bp|pvte.volmap_stock_ptr      " bb -> record stock
347           epbpab    bb|0                          " ab -> base of stock seg
348           eppab     ab|stock_seg.meters           " ab -> meters
349           tsx7      volmap$withdraw_from_volmap   " Replenish stock
350 
351           lda       bp|pvte.volmap_async_page
352           ana       -1,dl                         " Page number
353           tsx7      start_async_write             " Write it back
354           tra       post_meter_exit
355           tra       page_error$volmap_page_async_error " Not in memory
356 
357 post_write:
358           tsx6      page_fault$savex              " Recursive use of x7
359           lprpap    bp|pvte.volmap_astep          " ap -> ASTE for volmap_seg
360           ldq       ap|aste_size,al               " PTW
361           canq      ptw.er,dl                     " I/O Error
362           tze       post_write_noerr              " No
363           tsx7      io_error                      " Yes - handle
364           tra       post_idle                     " Set state to idle and notify
365 post_write_noerr:
366           canq      ptw.os,dl                     " I/O finished
367           tnz       page_fault$unsavex            " No
368 
369           canq      ptw.valid,dl                  " In memory
370           tze       post_write_not_mod            " No, write surely done
371           canq      ptw.phm+ptw.phm1,dl           " Page modified
372           tze       post_write_not_mod            " No, write completed
373 
374 "         Write posted but page modified. Possibly a race, although the locking
375 "         strategy should prevent this. More likely, the disk went offline.
376 "         In this case, the write is notified with no error by page control.
377 "         We recover by re-issuing the I/O
378 
379           spriap    arg+6                         " ptr -> ASTE of volmap_seg
380           eppap     arg+6
381           spriap    arg+2
382           lda       bp|pvte.volmap_async_page     " Page number in lower
383           ana       -1,dl
384           sta       arg+8
385           eppap     arg+8
386           spriap    arg+4
387           ldaq      pwrite_arg_list
388           staq      arg
389           call      page_fault$pwrite(arg)
390           tra       page_fault$unsavex
391 
392 post_write_not_mod:
393           lprpbb    bp|pvte.volmap_stock_ptr      " bb -> record stock
394           epbpab    bb|0                          " ab -> base of stock seg
395           eppab     ab|stock_seg.meters           " ab -> meters
396           tsx7      stock$reset_os                " Write finished, OK to use addresses
397 
398 post_idle:
399           stz       bp|pvte.volmap_async_state    " Idle
400 post_write_retry:
401           ldq       bp|pvte.volmap_idle_notify_word " Anybody waiting for idle
402           lda       bp|pvte.volmap_idle_notify_word
403           cana      pvte.volmap_idle_notify,dl
404           tze       post_meter_exit               " No
405           era       pvte.volmap_idle_notify,dl    " Reset notify switch
406           stacq     bp|pvte.volmap_idle_notify_word
407           tnz       post_write_retry              " Lost race
408 
409           eaa       bp|0                          " AU = PVTE offset
410           arl       18                            " AL = PVTE offset
411           ora       pvt$volmap_idle_wait_constant " Areg = wait event
412           sta       arg+4
413           eppap     arg+4
414           spriap    arg+2
415           ldaq      notify_arg_list
416           staq      arg
417           call      pxss$notify(arg)
418 
419 post_meter_exit:
420           increment ab|rsmeters.async_post_io_calls
421           read_clock
422           sbaq      post_io_start_time
423           adaq      ab|rsmeters.async_post_io_time
424           staq      ab|rsmeters.async_post_io_time
425           tra       page_fault$unsavex
426 
427 "^L
428 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
429 "
430 "         poll_io
431 "
432 "         call page$poll_volmap_io
433 "
434 "         Called with no locks held, wired and masked
435 "
436 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
437 
438 poll_io:
439           push
440           tsx6      page_fault$init_savex                   " Recursive use of x7
441 
442           tsx7      page_fault$lock_ptl                     " Spin lock
443 
444           ldq       pvte_size,dl                            " Index to last PVTE
445           mpy       pvt$n_entries
446           eax0      0,ql                                    " x0 -> one beyond end
447           stx0      volmap_page_temp_1                      " Save
448 poll_loop:
449           ldx0      volmap_page_temp_1                      " Restore PVTE index
450           eax0      -pvte_size,x0                           " One fewer to go
451           tmi       poll_done
452           stx0      volmap_page_temp_1                      " Save index to PVTE
453           eppbp     pvt$array
454           eppbp     bp|0,x0                                 " bp -> PVTE
455           ldq       bp|pvte.used_word
456           canq      pvte.used,dl                            " PVTE in use
457           tze       poll_loop                               " No - skip
458           ldx1      bp|pvte.volmap_async_state              " Asynchronous activity state
459           cmpx1     VOLMAP_ASYNC_IDLE,du                    " Idle
460           tze       poll_loop                               " Yes - skip
461 
462           sxl1      volmap_page_temp_1                      " Save async state
463           tsx7      post_io_pvtep                           " Try to post the I/O
464           lxl1      volmap_page_temp_1                      " Restore async state
465           cmpx1     bp|pvte.volmap_async_state              " Did state change?
466           tze       poll_loop                               " No
467           tsx7      page_error$poll_state_change            " Yes - report it
468           tra       poll_loop
469 
470 poll_done:
471           eppbb     sst$                                    " Needed by unlock_ptl
472           tsx7      page_fault$unlock_ptl
473           return
474 
475 
476 "^L
477 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
478 "
479 "         io_error - internal procedure to handle unrecoverable I/O error
480 "
481 "         tsx7      io_error
482 "
483 "         On entry,
484 "           bp -> PVTE
485 "           Areg = page number in volmap_seg
486 "
487 "         The strategy is to lose all free addresses on the page with the
488 "         I/O error. Any OS pages are flushed from the stock, and the
489 "         count of free addresses on that page is set to zero.
490 "
491 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
492 
493 io_error:
494           tsx6      page_fault$savex              " Recursive use of x7
495           sta       volmap_page_temp
496           lprpbb    bp|pvte.volmap_stock_ptr      " bb -> Record stock
497           epbpab    bb|0                          " ab -> base of stock_seg
498           eppab     ab|stock_seg.meters           " ab -> stock_seg$meters
499 
500           tsx7      stock$flush_os                " Flush any out-of-service addresses
501 
502           lda       volmap_page_temp              " Page number
503           ldx0      bp|pvte.nleft                 " Total number records left
504           sblx0     bb|record_stock.volmap_page,al " Minus number free this page
505           tpl       io_error_nleft_ok             " If positive
506           eax0      0
507 io_error_nleft_ok:
508           stx0      bp|pvte.nleft                 " Becomes new number left
509           eax0      0
510           stx0      bb|record_stock.volmap_page,al " Clear count of free this page
511           ldx0      bp|pvte.vol_trouble_count     " Increment the trouble count
512           adlx0     1,du
513           stx0      bp|pvte.vol_trouble_count
514 
515           tsx7      page_error$volmap_io_error    " Tell the world
516           tra       page_fault$unsavex            " And return
517 
518 "^L
519 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
520 "
521 "         check_valid_call - internal procedure to validate that
522 "         volume map is locked to this process, async state is idle,
523 "         and volmap_abs_seg is setup.
524 "
525 "         tsx6      check_valid_call
526 "
527 "         On entry,
528 "             bp -> PVTE
529 "
530 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
531 
532 check_valid_call:
533           ldx0      lp|volmap_abs_seg_link        " Segment number of volmap_abs_seg
534           adx0      lp|volmap_abs_seg_link        " Offset of SDW in DSEG
535           ldaq      dseg$0,x0                     " SDW
536           cmpaq     bp|pvte.volmap_seg_sdw        " The right one
537           tnz       page_error$volmap_page_invalid_call
538 
539           lda       pds$processid
540           cmpa      bp|pvte.volmap_lock           " Volmap lock held
541           tnz       page_error$volmap_page_invalid_call
542 
543           ldx0      bp|pvte.volmap_async_state    " State idle
544           cmpx0     VOLMAP_ASYNC_IDLE,du
545           tnz       page_error$volmap_page_invalid_call
546 
547           tra       0,x6
548 
549 
550 
551 
552           end