1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         * Copyright (c) 1976 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         * Copyright (c) 1972 by Massachusetts Institute of        *
 11         * Technology and Honeywell Information Systems, Inc.      *
 12         *                                                         *
 13         *********************************************************** */
 14 
 15 /* format: off */
 16 
 17 ioam_: proc;
 18 
 19 /* The I/O assignment manager - maintains a table of devices
 20    owned by various subsystems so that the subsystem can be
 21    notified if the process dies without properly detaching
 22    its devices.
 23 
 24    Rewritten 4/14/76 by Mike Grady.
 25 */
 26 
 27 
 28 /****^  HISTORY COMMENTS:
 29   1) change(86-09-17,Farley), approve(86-07-18,MCR7439),
 30      audit(86-09-24,Fawcett), install(86-10-20,MR12.0-1189):
 31      Changed to execute in the BCE environment.
 32                                                    END HISTORY COMMENTS */
 33 
 34 
 35 dcl  devx fixed bin,
 36      handler entry,
 37      code fixed bin (35),
 38      pid bit (36) aligned;
 39 
 40 dcl  ioat_uidc char (4) int static init ("ioat") options (constant),
 41      ioat_uid bit (36) based (addr (ioat_uidc));
 42 
 43 dcl  pds$processid bit (36) ext,
 44     (error_table_$bad_index,
 45      error_table_$dev_nt_assnd,
 46      error_table_$already_assigned,
 47      error_table_$ioat_err) fixed bin (35) ext;
 48 
 49 dcl  sys_info$service_system
 50      bit (1) aligned external static;
 51 
 52 dcl  ignore fixed bin (35),
 53      isize fixed bin,
 54      i fixed bin;
 55 
 56 dcl (addr, baseno, divide, fixed, hbound, rel, size) builtin;
 57 
 58 dcl  syserr_sw bit (1) int static init ("0"b);
 59 
 60 dcl  syserr entry options (variable),
 61      lock$wait entry (ptr, bit (36), fixed bin (35)),
 62      lock$unlock entry (ptr, bit (36));
 63 ^L
 64 dcl (ioatp, ioatep) ptr,
 65     (dseg$, ioat$) fixed bin ext;
 66 
 67 dcl 1 ioat aligned based (ioatp),                           /* The IO assigment table */
 68       2 lock bit (36),                                      /* lock while doing updates */
 69       2 last_entry fixed bin,                               /* highest entry used in table */
 70       2 max_entries fixed bin,                              /* highest entry we can use in table */
 71       2 entries (2048) like ioate;                          /* the ioat entries */
 72 
 73 dcl 1 ioate aligned based (ioatep),                         /* declaration of ioat entries */
 74       2 pid bit (36),                                       /* process id of this devices owner */
 75       2 devx fixed bin,                                     /* device index assigned by dstint */
 76       2 handler entry (fixed bin, fixed bin (35));          /* routine to call when process dies */
 77 ^L
 78 %include sdw;
 79 ^L
 80 assign: entry (devx, handler, code);                        /* entry to assign a device to a process */
 81 
 82           call setup;                                       /* init some stuff and set ptrs */
 83 
 84           call find_device (code);                          /* attempt to see if already assigned */
 85           if code = 0 then                                  /* it is already assigned to us */
 86                ioate.handler = handler;                     /* just update detach handler */
 87           else if code = error_table_$dev_nt_assnd then do; /* if not assigned, then assign it */
 88                call find_free;                              /* assign new block in ioat */
 89 
 90                ioate.pid = pds$processid;                   /* use this processid */
 91                ioate.devx = devx;                           /* fill in devx and */
 92                ioate.handler = handler;                     /* the unassign_handler */
 93                code = 0;                                    /* no error */
 94           end;
 95 
 96           if sys_info$service_system then
 97                call lock$unlock (ioatp, ioat_uid);          /* unlock IOAT */
 98           return;
 99 
100 
101 
102 unassign: entry (devx, code);                               /* entry to unassign a device from this process */
103 
104           call setup;
105           call find_device (code);                          /* it had better be our device */
106           if code = 0 then                                  /* it was ours, unassign */
107                ioate.pid = "0"b;                            /* clear processid to indicate entry free */
108 
109           if sys_info$service_system then
110                call lock$unlock (ioatp, ioat_uid);
111           return;
112 ^L
113 preempt: entry (pid, devx, code);                           /* entry to force the unassign of a device */
114 
115           call setup;                                       /* setup stuff */
116           call find_device (code);                          /* locate the device, it had better be assigned */
117           if code ^= error_table_$dev_nt_assnd then do;     /* if it was assigned at all, dump it */
118                call ioate.handler (ioate.devx, code);       /* call the detach handler */
119 
120                ioate.pid = "0"b;                            /* mark entry free */
121           end;
122 
123           if sys_info$service_system then
124                call lock$unlock (ioatp, ioat_uid);
125           return;
126 
127 
128 
129 process_release: entry (pid);                               /* entry to release all devices from a process */
130 
131           ioatp = addr (ioat$);                             /* make ptr, can't call setup */
132           if sys_info$service_system then do;
133                call lock$wait (ioatp, ioat_uid, ignore);    /* lock the IOAT lock */
134                if ignore ^= 0 then return;                  /* some locking error has occured */
135           end;
136 
137           do i = 1 to ioat.last_entry;                      /* search the table for this processid */
138                ioatep = addr (ioat.entries (i));            /* get entry ptr */
139 
140                if (ioate.pid ^= "0"b) & (ioate.pid = pid) then do; /* if owned and owned by this guy then */
141                     call ioate.handler (ioate.devx, ignore); /* call unassign handler, ignore code */
142                     ioate.pid = "0"b;                       /* free the slot */
143                end;
144           end;
145 
146           if sys_info$service_system then
147                call lock$unlock (ioatp, ioat_uid);
148           return;
149 ^L
150 setup: proc;                                                /* proc to setup ptrs and validate devx */
151 
152           if (devx < 0) | (devx > hbound (ioat.entries, 1)) then do;  /* validate the devx */
153                code = error_table_$bad_index;
154                goto RETURN;
155           end;
156 
157           code = 0;                                         /* initialize the code */
158           ioatp = addr (ioat$);                             /* get ptr  to the IOAT */
159 
160           if ioat.max_entries = 0 then do;                  /* init the max size of the IOAT */
161                sdwp = addr (dseg$);
162                sdwp = addr (sdwa (fixed (baseno (ioatp), 17))); /* get ptr to sdw */
163                isize = fixed (sdw.bound, 17) * 16;          /* get size of seg */
164 
165                isize = isize - fixed (rel (addr (ioat.entries)), 17); /* minus the header */
166                ioat.max_entries = divide (isize, size (ioate), 17, 0); /* divided by size of an entry */
167           end;
168 
169           if sys_info$service_system then do;
170                call lock$wait (ioatp, ioat_uid, code);      /* lock the IOAT */
171                if code ^= 0 then goto RETURN;               /* some locking error */
172           end;
173           return;
174 
175    end;
176 
177 
178 RETURN:   return;                                           /* non-local return */
179 
180 ^L
181 find_device: proc (acode);                                  /* proc to find the device in the IOAT */
182 
183 dcl acode fixed bin (35);
184 
185           acode = 0;                                        /* init the return code */
186           do i = 1 to ioat.last_entry;                      /* loop over whole IOAT */
187                ioatep = addr (ioat.entries (i));            /* get ptr to entry */
188 
189                if ioate.devx = devx then                    /* if we found devx then */
190                     if ioate.pid = pds$processid then return; /* and it is this process, we got it */
191                     else if ioate.pid = "0"b then do;       /* else if not assigned, say so */
192                          acode = error_table_$dev_nt_assnd;
193                          return;
194                     end;
195                     else do;                                /* else it is assigned, but not to us */
196                          acode = error_table_$already_assigned;
197                          return;
198                     end;
199           end;
200 
201           acode = error_table_$dev_nt_assnd;                /* devx not in table at all */
202           return;
203 
204    end;
205 
206 
207 
208 find_free: proc;
209 
210           do i = 1 to ioat.last_entry;                      /* search the IOAT for a free slot */
211                ioatep = addr (ioat.entries (i));            /* get ptr to this slot */
212                if ioate.pid = "0"b then return;             /* found a free slot */
213           end;
214 
215           if ioat.last_entry < ioat.max_entries then do;    /* if still room in IOAT at end, take one */
216                ioat.last_entry = ioat.last_entry + 1;       /* bump counter */
217                ioatep = addr (ioat.entries (ioat.last_entry)); /* set ptr */
218                return;
219           end;
220 
221           if ^syserr_sw then                                /* no more room in table, type message */
222                call syserr (3, "ioam_: The IOAT is too small, use TBLS config card to increase size.");
223           syserr_sw = "1"b;                                 /* message goes out only once */
224           code = error_table_$ioat_err;
225           goto RETURN;                                      /* jump back to caller */
226 
227    end;
228 
229 ^L
230 /* BEGIN MESSAGE DOCUMENTATION
231 
232 Message:
233 ioam_: The IOAT is too small, use TBLS config card to increase size.
234 
235 S:        $beep
236 
237 T:        $init
238 
239 M:        The system was unable to make an entry in the IO Assignment Table.
240 One or more devices may be unattachable.
241 
242 A:        $inform
243 Correct the configuration deck before the next bootload.
244 
245 
246 END MESSAGE DOCUMENTATION */
247 
248 end;