Mercurial > hg > Members > kono > os9 > sbc09
comparison CoCoOS9/level2v3/MODULES/pipeman_named.asm @ 31:bd2b07db8917 cocoos9lv2v3
CoCoOS9 version
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 14 Jul 2018 15:16:13 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
30:7b1b25ff010a | 31:bd2b07db8917 |
---|---|
1 ******************************************************************** | |
2 * PipeMan - OS-9 Level Two Named Pipe File Manager | |
3 * | |
4 * $Id: pipeman_named.asm,v 1.1.1.1 2001/02/21 23:30:55 boisy Exp $ | |
5 * | |
6 * Ed. Comments Who YY/MM/DD | |
7 * ------------------------------------------------------------------ | |
8 * Pipeman Modified to Include the SS.Ready KDM 86/02/23 | |
9 * I$GETSTT Call. | |
10 * Major Bug Corrected KDM 86/03/26 | |
11 * Upgraded to Level II version KDM 88/06/29 | |
12 * Added new labels and special defs | |
13 * Added code to detect EOF in SS.Ready | |
14 * Reformatted to make the module easier CJB 88/11/11 | |
15 * to understand during coding | |
16 * Added named pipes, etc for Level 2 upgrade CJB 88/12/03 | |
17 * Includes SS.SSig, SS.Relea, SS.Attr, SS.FD | |
18 * 1 Release 1.0 for Tandy CoCo OS9 CJB 88/12/26 | |
19 | |
20 nam PipeMan | |
21 ttl OS9 Level Two Named Pipe File Manager | |
22 | |
23 * | |
24 * Copyright 1981, 1985, 1986, 1988 by Microware Systems Corporation | |
25 * All Rights Reserved | |
26 * | |
27 * Named pipe code by Burke & Burke. | |
28 * All rights assigned to Microware Systems Corporation. | |
29 * | |
30 * This file contains proprietary information of Microware Systems | |
31 * Corporation. Persons accessing this file will be held strictly | |
32 * accountable for their use of the information herein. | |
33 * | |
34 | |
35 * | |
36 * PIPEMAN | |
37 * | |
38 * Pipe File Manager | |
39 * | |
40 * WARNING | |
41 * ------- | |
42 * | |
43 * Opening an existing named pipe emulates IOMan's I$Close and | |
44 * I$Dup calls. This file manager contains subroutines that | |
45 * mimic the current operation of IOMan. Any changes to IOMan's | |
46 * FMEXEC, I$Close or I$Dup calls must also be made to this code. | |
47 * | |
48 * Device Driver Static Storage Layout | |
49 * ----------------------------------- | |
50 * | |
51 * $00-$01 V.List Pointer in system map to pipe buffer for 1st | |
52 * pipe (16 bits). | |
53 * | |
54 * Pipe Buffer Data Structure | |
55 * -------------------------- | |
56 * | |
57 * $00-$01 PP.PD Pointer to shared path descriptor | |
58 * $02-$03 PP.Next Pointer to next pipe buffer in system map | |
59 * $04-$05 PP.Prev Pointer to previous pipe buffer in system map | |
60 * $06-$07 PP.Rsv2 Reserved | |
61 * | |
62 * $08 PP.Data Data buffer begins at this offset | |
63 * | |
64 * Path Descriptor Data Structure | |
65 * ------------------------------ | |
66 * | |
67 * $00 PD.PD Path number | |
68 * $01 PD.MOD Access permissions | |
69 * $02 PD.CNT Number of open images (e.g. I$DUP) | |
70 * $05 PD.CPR Current process ID | |
71 * $06-$07 PD.RGS Address of caller's register stack | |
72 * $08-$09 PD.BUF System space pipe buffer base pointer | |
73 *** PP.Read must have bit 4 clear; PP.Writ must be PP.Read XOR 4 | |
74 * $0A PD.Read No bytes -- offset only | |
75 * $0A PD.RPID Process ID of reader waiting on signal | |
76 * $0B PD.RCT Number of blocked readers | |
77 * $0C PD.RSIG Signal to send reader | |
78 * $0D PD.REOR Read EOR character | |
79 * $0E PD.Writ No bytes -- offset only | |
80 * $0E PD.WPID Process ID of writer waiting on signal | |
81 * $0F PD.WCT Number of blocked writers | |
82 * $10 PD.WSIG Signal to send writer | |
83 * $11 PD.WEOR Write EOR character (dummy) | |
84 *** End of special section | |
85 * $12-$13 PD.End Pointer to end of pipe buffer | |
86 * $14-$15 PD.NxtI Next in pointer | |
87 * $16-$17 PD.NxtO Next out pointer | |
88 * $18 PD.RFlg "Ready" flag | |
89 * $19 PD.Wrtn "Written" flag | |
90 * $1A-$1B PD.BCnt # queue elements currently bufered | |
91 * $1C PD.Own Process ID of pipe original creator | |
92 * $1D PD.Keep Non-zero if this pipe has been kept open artificially | |
93 * $1E-$1F PD.QSiz Max. size of queue (in elements) | |
94 * . | |
95 * . | |
96 * $20 PD.DTP Device type $02 = PIPE | |
97 * $21 PD.ESiz Size of each queue element | |
98 * $22-$23 PD.ECnt Max. elements in queue | |
99 * $23-$3F PD.Name Pipe name (after moving PD.ECnt to PD.QSiz) | |
100 * | |
101 | |
102 page | |
103 * | |
104 * Global equates | |
105 * | |
106 ifp1 | |
107 use defsfile | |
108 use pipedefs.l2v3 | |
109 * use rbfdefs | |
110 endc | |
111 | |
112 * | |
113 * Local Equates | |
114 * | |
115 | |
116 XVER equ 3 ;Version | |
117 | |
118 * ASCII CONTROL CHARACTERS | |
119 | |
120 CR equ $0D | |
121 | |
122 * CONDITION CODES | |
123 | |
124 NCARRY equ $00FE | |
125 | |
126 * PIPEMAN SPECIAL OFFSETS. | |
127 | |
128 PM.CPR equ PD.RPID-PD.READ | |
129 PM.CNT equ PD.RCT-PD.READ | |
130 PM.SIG equ PD.RSIG-PD.READ | |
131 PM.EOR equ PD.REOR-PD.READ | |
132 | |
133 * IOMAN special offsets. | |
134 * | |
135 * This constant is IOMAN release-dependent. | |
136 * It is the number of bytes between the entry stack | |
137 * pointer and the stacked PD pointer saved by *IOMAN*. | |
138 * Currently, the stack looks like this: | |
139 * | |
140 * A PL | |
141 * 9 PH <IOMAN post-SOPEN return address> | |
142 * 8 UL | |
143 * 7 UH | |
144 * 6 YL + | |
145 * 5 YH <PD pointer saved by IOMAN> | |
146 * 4 XL | |
147 * 3 XH | |
148 * 2 A | |
149 * 1 PL | |
150 * SP-> 0 PH <post OPEN/CREATE return address> | |
151 * <start of stack to be used by PIPEMAN> | |
152 | |
153 IOMAGIC equ 5 ;5 bytes to PD pointer | |
154 | |
155 * Local pipe buffer equates | |
156 | |
157 CInit equ %00100000 ;Set this bit to override PD queue parameters | |
158 | |
159 * Conditional assembly | |
160 | |
161 ANON set 0 ;Anonymous pipes only | |
162 NAMED set 1 ;Anonymous and named pipes | |
163 MSGS set 2 ;Both types of pipes, and message queues | |
164 WIZBANG set NAMED ;What features are we providing? | |
165 | |
166 NODIR set 0 ;Don't allow DIR on pipe devices | |
167 YESDIR set 1 ;Allow DIR on pipe devices | |
168 PIPEDIR set YESDIR ;Does DIR work on pipes? | |
169 | |
170 SLOWPD set 0 ;Slow PD location algorithm | |
171 QUICKPD set 1 ;Fast PD location algorithm | |
172 PDALGO set QUICKPD ;How to convert PD to system path # | |
173 | |
174 RECKLES set 0 ;Don't check for certain errors | |
175 CAREFUL set 1 ;Check for certain errors | |
176 CAUTION set CAREFUL | |
177 | |
178 page | |
179 * | |
180 * Module Header | |
181 * | |
182 | |
183 edition set 1 | |
184 | |
185 mod MODSIZE,MODNAM,FlMgr+Objct,ReEnt+XVER,JmpTbl,$0000 | |
186 | |
187 * Module Name | |
188 | |
189 MODNAM fcs "PipeMan" | |
190 fcb edition | |
191 | |
192 * Jump table | |
193 | |
194 JmpTbl lbra Create | |
195 lbra Open | |
196 lbra MakDir | |
197 lbra ChgDir | |
198 lbra Delete | |
199 lbra Seek | |
200 lbra Read | |
201 lbra Write | |
202 lbra ReadLn | |
203 lbra WriteLn | |
204 lbra GetStt | |
205 lbra SetStt | |
206 lbra Close | |
207 | |
208 page | |
209 * | |
210 * Create a named or anonymous pipe | |
211 * | |
212 * The size of the queue is determined by examining | |
213 * the path descriptor, since this information has | |
214 * been copied there from the device descriptor. | |
215 * | |
216 * Reg-U points to stacked registers of user. | |
217 * Reg-Y points to path descriptor | |
218 * | |
219 * If success, carry clear and X points to pipe buffer | |
220 * | |
221 | |
222 * Create function allows user to override both element | |
223 * count and element size. Override is enabled if if bit | |
224 * 5 of the access mode is set. For override, if MS bit | |
225 * of Reg-Y is clear, just use Reg-Y as queue element | |
226 * count. If MS bit of Reg-Y is set, use LS byte of | |
227 * Reg-Y as element size ($00 = no change) and bottom 7 | |
228 * bits of MS byte of Reg-Y as element count ($00 = no change) | |
229 | |
230 Create equ * | |
231 | |
232 lda R$A,U ;Get access mode | |
233 bita #CInit | |
234 beq Open | |
235 | |
236 * Handle queue size override | |
237 | |
238 ldd R$Y,U ;Get queue size initializer | |
239 bpl SetCnt ; (branch if just setting count) | |
240 | |
241 * Set element size and count | |
242 | |
243 tstb | |
244 beq Creat00 ; (branch if using default size) | |
245 | |
246 stb PD.ESiz,Y ;Reg-B = size of each element | |
247 | |
248 Creat00 anda #$7F | |
249 beq Open ; (branch if using default count) | |
250 | |
251 tfr a,B | |
252 clra | |
253 | |
254 * Set number of elements in queue from Reg-D | |
255 | |
256 SetCnt std PD.ECnt,Y ;Reg-D = number of elements | |
257 | |
258 * Enter here for normal OPEN | |
259 | |
260 Open equ * | |
261 | |
262 * Move number of elements in queue to make room for name | |
263 | |
264 ldd PD.ECnt,Y | |
265 std PD.QSiz,Y | |
266 | |
267 * Parse pathname | |
268 | |
269 clrb ;Assume anonymous pipe | |
270 clra ;Assume not 1st pipe | |
271 ldx R$X,U ;Point at file name in user's space | |
272 pshs U,Y,X,D ;Save file name, PD, reg. base, 1st & anon flag | |
273 | |
274 * Caller's Regs Ptr | |
275 * PD Ptr | |
276 * Path name uptr | |
277 * Named flag | |
278 * SP-> First flag | |
279 | |
280 os9 F$PrsNam ;Error if driver name (e.g. /pipe) invalid | |
281 bcs BadName | |
282 | |
283 * See if named or anonymous pipe requested. | |
284 | |
285 lbsr GtNext ;Return CC=MI if at end of path name | |
286 cmpa #'/ | |
287 beq HasName | |
288 | |
289 * /pipe____ | |
290 * X Y | |
291 * Pipe is anonymous -- set up dummy name in PD. | |
292 * Stack must match the named pipe setup | |
293 | |
294 NotName tfr Y,X ;Skip any trailing blanks | |
295 os9 F$PrsNam ; (should return carry set) | |
296 ldd #1 ;Length of dummy name | |
297 pshs Y,X,D | |
298 | |
299 ldy 10,S ;Get PD pointer | |
300 clr PD.Name,Y ; and set dummy name | |
301 | |
302 bra GoCheck | |
303 | |
304 * /pipe/foo____ | |
305 * X Y | |
306 * Pipe is named -- check length and flag on stack | |
307 | |
308 HasName tfr Y,X | |
309 os9 F$PrsNam ;Scan off the name | |
310 bcs BadName | |
311 | |
312 cmpb #NameMax ;Check length of name | |
313 bhi BadName | |
314 | |
315 * Length OK. X points to start of name, Y to end of name, | |
316 * B has name length. | |
317 * Save registers & length, and do final parse to skip white | |
318 | |
319 com 1,S ;Set "named" flag | |
320 clra | |
321 pshs Y,X,D | |
322 | |
323 tfr Y,X | |
324 os9 F$PrsNam ;Error if trying for pipe subdirectory | |
325 bcc BadNam2 | |
326 | |
327 * /pipe/foo____ | |
328 * X Y | |
329 * Need to get the pipe name into our address space | |
330 * Use the PD for a temporary buffer. | |
331 | |
332 NameOK ldx <D.Proc ;Pointer to caller's PD | |
333 lda P$Task,X ; get caller's DAT image # | |
334 ldx <D.SysPrc ;Pointer to our PD | |
335 ldb P$Task,X ; get system's DAT image # | |
336 ldy 0,S ;Byte count | |
337 ldx 2,S ;Source address | |
338 ldu 10,S ;Get PD pointer and convert to . . . | |
339 leau PD.Name,U ;Destination address | |
340 lbsr MovSet ;Move block, set MSB of last byte. | |
341 | |
342 * Wow! Everybody's in the same address space now. | |
343 | |
344 * Since this is a named pipe, force mode to UPDATE. | |
345 * Also, do not permit DIR. access | |
346 | |
347 ldx 10,S | |
348 lda PD.MOD,X | |
349 bita #DIR. | |
350 bne BadNam2 | |
351 | |
352 ora #(READ.+WRITE.) | |
353 sta PD.MOD,X | |
354 | |
355 * See if this is an existing pipe. To do this, we | |
356 * must get the linked list head pointer from the | |
357 * device driver's static storage. | |
358 * | |
359 * Stack looks like this: | |
360 * | |
361 * C 2 Sysmap Reg Pointer | |
362 * A 2 Sysmap PD Pointer | |
363 * 8 2 Usrmap Path name pointer | |
364 * 7 1 Named pipe flag | |
365 * 6 1 First pipe flag | |
366 * 4 2 Usrmap Pipe name end pointer | |
367 * 2 2 Usrmap Pipe name start pointer | |
368 * 0 2 Name length | |
369 * sp-> | |
370 | |
371 GoCheck ldx 10,S ;Get PD pointer | |
372 ldx PD.DEV,X ;Get device table pointer | |
373 ldu V$Stat,X ;Get static storage pointer | |
374 ldx V.List,U ;Get pointer to head of pipe bfr linked list | |
375 bne Not1st ; (reg-X = $0000 if no previous pipes) | |
376 | |
377 * This is the 1st pipe for this descriptor. | |
378 * Reg-X = $0000 | |
379 * Set flag and process as a new pipe. | |
380 | |
381 com 6,S ;This is the first pipe | |
382 bra NewPipe ;This is a new pipe | |
383 | |
384 * No time like the present for some error handlers | |
385 | |
386 * Generic error, cleaning stack | |
387 | |
388 BadXit2 leas 8,S | |
389 coma ;Set carry | |
390 rts | |
391 | |
392 * Bad Pathname -- 2 versions, depending on | |
393 * how much junk is on the stack. | |
394 | |
395 BadNam2 leas 6,S ;Clean stack | |
396 BadName ldb #E$BPNam | |
397 bra BadXit2 | |
398 | |
399 * Not Enough System RAM | |
400 | |
401 TooBig ldb #E$NoRAM | |
402 BadExit leas 6,S ;Clean stack | |
403 bra BadXit2 | |
404 | |
405 * Look up the pipe name, unless the pipe is anonymous. | |
406 * | |
407 * Reg-U points to driver static storage. | |
408 * Reg-X points to next pipe buffer to check. | |
409 | |
410 Not1st tst 7,S ;Unnamed pipes are always new | |
411 beq NewPipe | |
412 | |
413 ldy 10,S ;point at PD | |
414 leay PD.Name,Y ; then point at name in PD | |
415 | |
416 * Main loop. Always at least 1 pipe buffer to check first time through. | |
417 * Reg-X points to buffer to check, or $0000 if none. | |
418 * Reg-Y points to desired pipe name. | |
419 | |
420 ChkLoop pshs X | |
421 ldx PP.PD,X ;Point at PD for this pipe buffer | |
422 leax PD.Name,X ; and then point at name stored in PD | |
423 lbsr Compare | |
424 puls X | |
425 lbeq OldPipe ; (got a match) | |
426 | |
427 ldd PP.Next,X ;Don't fall off the edge | |
428 beq NewPipe ; (end of list) | |
429 | |
430 tfr D,X ;Advance to next buffer | |
431 bra ChkLoop | |
432 | |
433 * Pipe name not found. Create a new pipe. | |
434 * | |
435 * Reg-U points to driver static storage. | |
436 * Reg-X points to last pipe buffer checked ($0000 if 1st pipe) | |
437 | |
438 NewPipe ldy 10,S ;Get PD pointer | |
439 | |
440 ifeq (PIPEDIR-YESDIR) | |
441 lda PD.MOD,Y ;Check pipe attributes | |
442 bita #DIR. | |
443 beq NEWP1 | |
444 | |
445 * Initialize pipe characteristics for DIR. bit set | |
446 | |
447 lbsr SizDirP | |
448 * beq XYZZY ;Special if no pipes created | |
449 endc | |
450 | |
451 * Normal (non-dir) processing | |
452 | |
453 NewP1 ldd PD.QSiz,Y ;Get max element count | |
454 bne DoNew ; (graceful operation if no count) | |
455 | |
456 * Default pipe parameters if none in PD. | |
457 | |
458 ldd #$0100 ;Assume 256 byte buffer, 1 byte element | |
459 sta PD.ESiz,Y ;Reg-A = 1 | |
460 subd #PP.Data ;Compute elements for total size = 256 | |
461 std PD.QSiz,Y Use parameters in PD | |
462 | |
463 DoNew lbsr ECtoBC ;Convert element count to byte count in D | |
464 bcs TooBig ; (carry set if too big) | |
465 | |
466 * Carry has exit status | |
467 * Reg-D = # bytes for queue, w/o overhead | |
468 * Reg-X = previous buffer | |
469 * Reg-U = driver static storage | |
470 | |
471 tfr U,Y ;Save static storage pointer | |
472 | |
473 addd #PP.Data ;Add in overhead | |
474 bcs TooBig | |
475 | |
476 pshs D ;Save buffer size | |
477 os9 F$SrqMem ;Attempt to allocate buffer | |
478 puls D ;Recover size, clean stack, lose error msg | |
479 bcs TooBig | |
480 | |
481 * Found enough memory for pipe buffer. | |
482 * | |
483 * Pointer in Reg-U | |
484 * Size in Reg-D | |
485 * Previous buffer in Reg-X. | |
486 * Driver static storage in Reg-Y. | |
487 * | |
488 * Initialize the buffer | |
489 | |
490 pshs U,D ;Save buffer pointer & size | |
491 | |
492 * Clear pipe buffer header | |
493 | |
494 ldb #PP.Data ;Size of header | |
495 ClrBuf clr ,U+ | |
496 decb | |
497 bne ClrBuf | |
498 | |
499 puls D,U | |
500 | |
501 * Initialize path descriptor and other fields of pipe buffer | |
502 * for new pipe. | |
503 * | |
504 * Pointer in Reg-U | |
505 * Size in Reg-D | |
506 * Previous buffer in Reg-X. | |
507 * Driver static storage in Reg-Y. | |
508 * | |
509 * IOMan has already prefilled the PD to $00 and | |
510 * has set PD.CNT for this path to 1. | |
511 | |
512 pshs Y,X ;Save static storage pointer & prev.buff | |
513 | |
514 ldy (4+10),S ;Get PD pointer to Reg-Y | |
515 sty PP.PD,U ;Save pointer to PD in pipe buffer | |
516 | |
517 leax D,U ;Point to end of pipe.buff + 1 | |
518 stx PD.End,Y | |
519 | |
520 leax PP.Data,U ;Initial Next in & Next out pointers | |
521 stx PD.NxtI,Y | |
522 stx PD.NxtO,Y | |
523 | |
524 ldx <D.Proc ;Save ID of original creator | |
525 lda P$ID,X | |
526 sta PD.Own,Y | |
527 | |
528 puls Y,X ;Recover static storage pointer and prev.buff | |
529 | |
530 stx PP.Prev,U ;Save address of previous buffer ($0 if none) | |
531 bne LinkIn ; (branch if this isn't the 1st pipe) | |
532 | |
533 * Special -- this is the first pipe. | |
534 * Set PP.Next to $0000 and store buffer address in device memory. | |
535 * | |
536 * Reg-U = pointer to new buffer. | |
537 * Reg-X = $0000. | |
538 * Reg-Y = static storage | |
539 | |
540 ** Zero prefill of PP header covers this | |
541 ** stx PP.Next,U ;No next buffer | |
542 ** stx PP.Prev,U ;No previous buffer | |
543 stu V.List,Y ;Point driver static at this buffer | |
544 bra IsAsOld | |
545 | |
546 * There are other named pipes. Link this one in correctly | |
547 * after the last one checked. | |
548 * | |
549 * Reg-U = pointer to new buffer. | |
550 * Reg-X = Pointer to previous buffer. | |
551 * Reg-Y = static storage. | |
552 | |
553 LinkIn ldd PP.Next,X ;Get old's next (could be $0000) | |
554 stu PP.Next,X ;Set old's next pointing at new | |
555 std PP.Next,U ;Set new's next where old's was | |
556 stx PP.Prev,U ;Set new's prev pointing at old | |
557 pshs X,D | |
558 ldx 0,S ;Point X at original old's next | |
559 beq Link9 ; (branch if no next -- $0000 set already) | |
560 stu PP.Prev,X ;Set prev of old's original next to new | |
561 Link9 puls D,X | |
562 | |
563 * Now we look pretty much like a new access to an old pipe. | |
564 * Fix up pointers to match "old pipe" code | |
565 | |
566 IsAsOld tfr U,X ;Point Reg-X at pipe buffer | |
567 tfr Y,U ;Point Reg-U at driver static storage | |
568 ldy 10,S ;Recover PD pointer | |
569 stx PD.BUF,Y ;Set up buffer pointer in PD | |
570 bra OpnXit ; (go to common trailer code) | |
571 | |
572 * Pipe name found. Set up to access an old pipe. | |
573 * | |
574 * Reg-U points to driver static storage. | |
575 * Reg-X points to matching pipe buffer. | |
576 * | |
577 * We need to make this look like a DUP call, so | |
578 * there's some nasty code here to give back the | |
579 * PD allocated by IOMan and go get the "original" | |
580 * PD for this named pipe. | |
581 | |
582 OldPipe equ * | |
583 | |
584 *** *** | |
585 * WARNING -- This code emulates IOMan's I$Close and I$Dup * | |
586 *** *** | |
587 | |
588 * | |
589 * Processing to give back the new path descriptor and use | |
590 * the original PD that the pipe was opened with. | |
591 * | |
592 * Fake close of PD passed by IOMan | |
593 * Fake dup of named pipe's "master" PD | |
594 * Fix PD pointer saved on IOMAN's stack | |
595 * | |
596 * All of the subroutines preserve all regs, except as noted | |
597 * This section MUST preserve Reg-X and Reg-U. There must | |
598 * be exactly 14 bytes on the stack at this point. | |
599 | |
600 ldy 10,S ;Get IOMAN PD pointer (original Reg-Y) | |
601 | |
602 * Detach the path. | |
603 | |
604 pshs U | |
605 ldu PD.DEV,Y ; Get device pointer | |
606 os9 I$Detach ; Detach to compensate for IOMAN Attach | |
607 puls U | |
608 | |
609 * Decrement use count | |
610 | |
611 dec PD.CNT,Y ;Decrement use count | |
612 | |
613 * Give back unwanted PD | |
614 | |
615 *** This is the way I did it originally | |
616 pshs X | |
617 lda PD.PD,Y ;Get system path number | |
618 ldx <D.PthDBT ;Point at path table index | |
619 os9 F$Ret64 ; and give back descriptor | |
620 puls X | |
621 *** This is the way the OSK named pipe manager does it. | |
622 *** I had to translate, of course, but the translated | |
623 *** version doesn't work right. | |
624 * pshs U,X | |
625 * lda PD.PD,Y ;Get system path # | |
626 * ldx <D.PthDBT ;Point at path table index | |
627 * ldu <D.SysDis ;Point at system SVC dispatch table | |
628 * jsr [(F$Ret64*2),U] ;Do a RET64 | |
629 * puls X,U | |
630 | |
631 * Stack clean. | |
632 * Update IOMAN variables. | |
633 * Reg-Y = where IOMAN thinks the PD is. | |
634 | |
635 ifeq (CAUTION-CAREFUL) | |
636 cmpy (14+IOMAGIC),S ;Make sure the stack looks right (PD matches) | |
637 beq OKMagic | |
638 | |
639 * Stack is wrong; declare bad magic! | |
640 | |
641 comb | |
642 ldb #E$Bug | |
643 leas 14,S | |
644 rts | |
645 endc | |
646 | |
647 * Stack is right; go fix PD pointers | |
648 | |
649 OKMagic ldy PP.PD,X ;Get PD pointer of existing named pipe PD. | |
650 sty 10,S ;Point PD pointer at existing PD | |
651 sty (14+IOMAGIC),S ;Save new IOMAN PD pointer in IOMAN stack | |
652 inc PD.CNT,Y ;Increment use count | |
653 | |
654 * End of dangerous code | |
655 * This section MUST have preserved Reg-X and Reg-U | |
656 | |
657 * Exit code. | |
658 * | |
659 * Reg-U points to driver static storage. | |
660 * Reg-Y points to PD. | |
661 * Reg-X points to matching pipe buffer. | |
662 * | |
663 * Advance caller's path name pointer | |
664 | |
665 OpnXit equ * | |
666 | |
667 * Fix use count based on PD.Keep | |
668 | |
669 lda PD.CNT,Y | |
670 suba PD.Keep,Y | |
671 sta PD.CNT,Y ;Get rid of any artificial openings | |
672 clr PD.Keep,Y | |
673 | |
674 ifeq (PIPEDIR-YESDIR) | |
675 * Handle prefill of pipe directory buffer | |
676 | |
677 lda PD.Mod,Y ;Is this a DIR. open? | |
678 bita #DIR. | |
679 beq OpnXt2 | |
680 | |
681 lbsr FilDirP ;Send directory info to pipe | |
682 endc | |
683 | |
684 OpnXt2 ldu 12,S ;Point at caller's registers | |
685 ldd 4,S ;Get revised path name pointer | |
686 std R$X,U | |
687 | |
688 leas 14,S ;Clean the stack | |
689 | |
690 * Successful exit. Reg-X points to pipe buffer. | |
691 | |
692 clrb | |
693 rts | |
694 | |
695 page | |
696 * | |
697 * Compare pipe names. | |
698 * | |
699 * Can't use F$CmpNam here because the strings | |
700 * are in system space. | |
701 * | |
702 * Path names are pointed to by Reg-X and Reg-Y. | |
703 * Case is ignored. Returns NE if not equal, else | |
704 * EQ. | |
705 * | |
706 | |
707 Compare pshs Y,X,A ;Reg-A is temp. storage | |
708 | |
709 * Main comparison loop | |
710 | |
711 Cmp001 lda ,X+ | |
712 anda #%11011111 ;Cheap and fast TOUPPER | |
713 sta 0,S | |
714 | |
715 lda ,Y+ | |
716 anda #%11011111 ;Cheap and fast TOUPPER | |
717 bmi Cmp.Y ; (exit if we find end of Y-string) | |
718 | |
719 cmpa 0,S | |
720 beq Cmp001 | |
721 | |
722 * Names don't match. Return CC=NE | |
723 | |
724 puls A,X,Y,PC | |
725 | |
726 * End of "Y" string. "X" character either matches or | |
727 * it doesn't. Return CC accordingly. | |
728 | |
729 Cmp.Y cmpa 0,S | |
730 puls A,X,Y,PC | |
731 | |
732 * | |
733 * Convert element count in D to byte count in D. | |
734 * Return carry set if too big. | |
735 * | |
736 * Reg-Y = PD pointer | |
737 * Reg-D = Element count | |
738 * | |
739 | |
740 ECtoBC pshs D | |
741 lda PD.ESiz,Y ;Get size of each element | |
742 ldb 0,S ;Get MSB of element count | |
743 mul | |
744 pshs D | |
745 lda PD.ESiz,Y ;Get size of each element | |
746 ldb (2+1),S ;Get LSB of element count | |
747 mul | |
748 adda 1,S ;C-bit set if too big | |
749 tst ,S++ ;Z-bit clear if too big, C-bit OK | |
750 leas 2,S | |
751 bcs EB.err | |
752 bne EB.err | |
753 | |
754 * OK exit | |
755 andcc #$FE | |
756 rts | |
757 | |
758 * Error exit | |
759 EB.err orcc #$01 | |
760 rts | |
761 | |
762 * Get next character of path name. | |
763 * Reg-Y set up as if just did a PRSNAM. | |
764 | |
765 GtNext ldx <D.Proc | |
766 ldb P$Task,X | |
767 tfr Y,X | |
768 os9 F$LDABX | |
769 rts | |
770 | |
771 page | |
772 * | |
773 * Error hook | |
774 * | |
775 MAKDIR equ * | |
776 CHGDIR equ * | |
777 UNKNOWN comb | |
778 ldb #E$UNKSVC | |
779 rts | |
780 | |
781 page | |
782 * | |
783 * Close a pipe | |
784 * | |
785 * If there are any other pipe users, leave the pipe | |
786 * around. Also, if the pipe is named and contains | |
787 * any data, leave the pipe around even if there are | |
788 * no remaining pipe users. | |
789 * | |
790 * PD.Keep will be non-zero if the pipe has been kept | |
791 * open artificially. | |
792 * | |
793 * This routine is called each time a path to the pipe | |
794 * is closed. | |
795 * | |
796 | |
797 CLOSE equ * | |
798 | |
799 * Account for extra use count if pipe artificially kept open. | |
800 * Then see if this is the last user of the pipe | |
801 | |
802 lda PD.Keep,Y ;Account for extra pipe images | |
803 nega | |
804 clr PD.Keep,Y | |
805 adda PD.CNT,Y | |
806 sta PD.CNT,Y ;Set correct PD.CNT value | |
807 bne READERS ; and branch if any users left | |
808 | |
809 * No open paths to this pipe. | |
810 * If it's named and not empty, leave it around anyway. | |
811 | |
812 tst PD.Name,Y ;Named pipe? | |
813 beq CLOSE2 | |
814 | |
815 ldd PD.BCnt,Y ;How many elements buffered on named pipe? | |
816 beq CLOSE2 | |
817 | |
818 * Leave this named pipe around for a while | |
819 | |
820 inc PD.CNT,Y ;Create an extra image | |
821 inc PD.Keep,Y ; and remember that we did it | |
822 bra CLOXIT | |
823 | |
824 * Delete the pipe. | |
825 * Y = PD pointer. | |
826 | |
827 CLOSE2 bsr ZapPipe | |
828 bra CloXit ;No error | |
829 | |
830 * Open paths left. What kind? | |
831 | |
832 READERS cmpa PD.RCT,Y ;Are all open paths readers? | |
833 bne WRITERS | |
834 | |
835 * All other open paths are readers. | |
836 * Send signal to next reader (let him read a bit) | |
837 | |
838 leax PD.Read,Y | |
839 bra SENDSIG | |
840 | |
841 * Not all readers. What kind? | |
842 | |
843 WRITERS cmpa PD.WCT,Y ;Are all open paths writers? | |
844 bne CloXit | |
845 | |
846 * All other open paths are writers. | |
847 * Send signal to next writer (let him write a bit) | |
848 | |
849 leax PD.Writ,Y | |
850 | |
851 * Send signal to next reader or writer | |
852 | |
853 SENDSIG lda PM.CPR,X ;Process ID to signal | |
854 beq CLOXIT | |
855 | |
856 ldb PM.SIG,X ;Signal code to send | |
857 beq CLOXIT | |
858 | |
859 * Committed to send signal: clear the flag and send it | |
860 | |
861 clr PM.SIG,X ;Force no pending signal | |
862 os9 F$SEND | |
863 | |
864 * Done with close | |
865 | |
866 CLOXIT clrb | |
867 rts | |
868 | |
869 page | |
870 * | |
871 * Delete a named pipe. | |
872 * | |
873 * Reg-Y = PD | |
874 * Reg-U = caller's registers | |
875 * Reg-X = path name | |
876 * | |
877 | |
878 Delete lda #Read. | |
879 sta PD.MOD,Y ;Need only READ permission | |
880 pshs U,Y,X,A ;***Match stack set up by IOMAN | |
881 lbsr Open ;Try to open the pipe | |
882 puls U,Y,X,A ;***Clean up special stack | |
883 bcs BadDel | |
884 | |
885 * Disconnect from pipe, but keep pointer. | |
886 * Then check to see if we're the only user. | |
887 * | |
888 * Note -- The call to OPEN updated PD.CNT | |
889 * and cleared PD.Keep. | |
890 | |
891 dec PD.CNT,Y ;Don't count ourselves | |
892 beq DoDel ;If count is zero, OK to delete | |
893 | |
894 * Pipe is in use. Return E$FNA | |
895 | |
896 FNAXIT comb | |
897 ldb #E$FNA | |
898 | |
899 * Exit w/ carry set and error code in B | |
900 | |
901 BadDel rts | |
902 | |
903 * Perform the delete. | |
904 | |
905 DoDel bsr ZapPipe | |
906 clrb | |
907 rts | |
908 | |
909 * | |
910 * Return all memory for the pipe buffer specified | |
911 * in the path descriptor, and remove it from the linked list. | |
912 * | |
913 * Reg-Y = PD pointer | |
914 * Pipe buffer pointer is at PD.BUF,Y | |
915 * | |
916 | |
917 ZapPipe ldu PD.DEV,Y ;Get device table pointer | |
918 ldu V$Stat,U ;Get static storage pointer | |
919 | |
920 ldx PD.BUF,Y ;Point to pipe's buffer | |
921 ldd PP.Next,X ;Save pointer to current and next in list | |
922 pshs D | |
923 ldd PP.Prev,X ;Save pointer to previous in list | |
924 pshs D | |
925 | |
926 * Reg-D has pointer to previous. If zero, we're zapping head of list. | |
927 * Z-bit is already set accordingly | |
928 | |
929 bne OldHead | |
930 | |
931 * New head of list. | |
932 * Reg-X still points to buffer to be deleted | |
933 | |
934 ldd 2,S ;Get pointer to next (may be $0000) | |
935 std V.List,U ; and set as new head | |
936 pshs X,D | |
937 ldx 0,S ;Point Reg-X at next, set CC | |
938 beq Zap9 | |
939 clr (PP.Prev+0),X ; and set no prev for next | |
940 clr (PP.Prev+1),X | |
941 Zap9 puls D,X ;Point back at pipe to delete | |
942 bra ZapIt | |
943 | |
944 * No new head of list. Just delete from linked list. | |
945 * We know there is a previous buffer. | |
946 * | |
947 * Reg-X points to buffer to be deleted. | |
948 * Reg-D points to previous buffer. | |
949 | |
950 OldHead ldu PP.Next,X ;Get U pointing at our next (may be $0000) | |
951 exg D,X ;Point X at our prev, D at us | |
952 stu PP.Next,X ;Save new next for out prev | |
953 beq Zap8 | |
954 stx PP.Prev,U ;Point our next's prev at our original prev | |
955 Zap8 exg D,X | |
956 | |
957 * All cleaned up. Give back the buffer | |
958 * Reg-X points to buffer, Reg-Y points to PD. | |
959 | |
960 ZapIt ldd PD.End,Y | |
961 pshs X | |
962 subd 0,S ;Get total bytes to Reg-D | |
963 puls U ;Point at buffer, clean stack | |
964 os9 F$SRtMem | |
965 | |
966 * Exit with whatever error F$SRtMem produces | |
967 | |
968 leas 4,S ;Clean stack | |
969 rts | |
970 | |
971 page | |
972 * | |
973 * Dummy hook | |
974 * | |
975 SEEK equ * | |
976 Dummy clrb | |
977 rts | |
978 | |
979 page | |
980 * | |
981 * GETSTT processing | |
982 * | |
983 * Supports the following codes: | |
984 * | |
985 * SS.Opt Option section | |
986 * SS.Ready # bytes in queue | |
987 * SS.Siz Size of queue | |
988 * SS.EOF Queue empty | |
989 * SS.FD Bogus file descriptor (WIZBANG==MSGS) | |
990 * SS.ScSiz Screen Size | |
991 * | |
992 * SS.Opt handled in IOMAN, etc. | |
993 * SS.Ready code by Kent Meyers, modified by Chris Burke | |
994 * SS.Siz, SS.EOF, SS.FD, SS.ScSiz by Chris Burke | |
995 * | |
996 | |
997 GETSTT lda R$B,U Get User B Register ++ | |
998 cmpa #SS.READY Test for Ready Call ++ | |
999 bne NotSSRDY | |
1000 | |
1001 * Process SS.Rdy -- return # elements in queue | |
1002 * If more than 255, return 255. | |
1003 | |
1004 G.Rdy ldb #255 | |
1005 tst (PD.BCnt+0),Y | |
1006 bne G.Rdy0 ;Accomodate large queues (256 or more bytes) | |
1007 ldb (PD.BCnt+1),X ;Get element count LSB | |
1008 | |
1009 * Reg-B has LSB of element count, CC set based on value | |
1010 | |
1011 beq RDNRDY ;Not Ready if no characters | |
1012 | |
1013 G.Rdy0 stb R$B,U ;Return count in B | |
1014 | |
1015 SST.OK equ * | |
1016 SST.Ign equ * | |
1017 | |
1018 G.OK clrb No Error ++ | |
1019 tfr CC,A | |
1020 sta R$CC,U | |
1021 rts Return ++ | |
1022 | |
1023 * No characters for SS.Ready | |
1024 | |
1025 RDNRDY tst PD.Wrtn,Y Anybody writing to pipe? | |
1026 bne NOTEOF (not OK if so) | |
1027 | |
1028 * No writer | |
1029 | |
1030 ldb PD.CNT,Y Exactly one path open to pipe? | |
1031 decb | |
1032 bne NOTEOF (OK if no, e.g. nobody or > 1) | |
1033 | |
1034 * Internal error | |
1035 | |
1036 IntErr comb | |
1037 ldb #255 | |
1038 rts | |
1039 | |
1040 NOTEOF comb Set Error Flag ++ | |
1041 ldb #E$NOTRDY Get Error Code ++ | |
1042 rts Return ++ | |
1043 | |
1044 * Not SS.Ready. Check for SS.Siz | |
1045 | |
1046 NotSSRdy cmpa #SS.Size Test for Size call | |
1047 bne NotSSSiz | |
1048 | |
1049 * Process SS.Siz -- return size of queue in ELEMENTS. | |
1050 | |
1051 G.Siz ldd PD.QSiz,Y ;Get max. # of queue elements | |
1052 std R$U,U | |
1053 clr (R$X+0),U Set 16 MSB's to $0000 | |
1054 clr (R$X+1),U | |
1055 GOK001 bra G.OK | |
1056 | |
1057 * Not SS.Siz. Check for SS.EOF | |
1058 | |
1059 NotSSSiz cmpa #SS.EOF | |
1060 bne NotSSEOF | |
1061 | |
1062 * Process SS.EOF | |
1063 * Handle like SS.Rdy, but preserve Reg-B | |
1064 | |
1065 G.EOF bsr G.Siz | |
1066 ldb #0 ;NOT clrb -- preserve carry | |
1067 stb R$B,U | |
1068 bcc G.OK ;No error if ready | |
1069 | |
1070 ldb #E$EOF ;Carry is already set | |
1071 rts | |
1072 | |
1073 * Not SS.EOF. Check for SS.FD | |
1074 | |
1075 ifeq (PIPEDIR-YESDIR) | |
1076 NotSSEOF cmpa #SS.FD | |
1077 bne NotSSFD | |
1078 | |
1079 * Process SS.FD | |
1080 | |
1081 lbsr DoSSFD | |
1082 bra G.OK ;Successful always | |
1083 else | |
1084 NotSSEOF equ * | |
1085 endc | |
1086 | |
1087 * Not SS.FD. Check for SS.ScSiz | |
1088 | |
1089 NotSSFD cmpa #SS.ScSiz ;Force UNKNOWN here | |
1090 lbeq UnKnown | |
1091 | |
1092 NotSCSZ equ * | |
1093 | |
1094 NotSSAT equ * | |
1095 | |
1096 * Process unknown GETSTT | |
1097 | |
1098 * lbra UNKNOWN | |
1099 bra G.OK | |
1100 * bra NotEOF | |
1101 | |
1102 page | |
1103 * | |
1104 * SETSTT processing | |
1105 * | |
1106 * Supports the following codes: | |
1107 * | |
1108 * SS.Opt Option section | |
1109 * SS.Siz No effect unless size=0; then clears pipe buffer | |
1110 * SS.FD No effect | |
1111 * SS.SSig Set signal on data available | |
1112 * SS.Relea Release signal | |
1113 * | |
1114 * SS.Opt handled in IOMAN, etc. | |
1115 * SS.Siz, SS.SSig, SS.Relea by Chris Burke, modified | |
1116 * from OSK. | |
1117 * | |
1118 | |
1119 SetStt lda R$B,U Get User B Register ++ | |
1120 cmpa #SS.Opt | |
1121 beq SST.Ign ; (ignore) | |
1122 cmpa #SS.FD | |
1123 beq SST.Ign | |
1124 | |
1125 * Check for SS.SIZ | |
1126 | |
1127 cmpa #SS.Size | |
1128 bne NoS.Siz | |
1129 | |
1130 ldd R$U,U ;Get caller's size | |
1131 bne SST.Ign | |
1132 | |
1133 * Clear the pipe | |
1134 | |
1135 ldx PD.Buf,Y | |
1136 leau PP.Data,X | |
1137 stu PD.NxtI,Y | |
1138 stu PD.NxtO,Y | |
1139 clr (PD.BCnt+0),Y | |
1140 clr (PD.BCnt+1),Y | |
1141 clr PD.RFlg,Y | |
1142 clr PD.Wrtn,Y | |
1143 | |
1144 QST.OK bra SST.OK | |
1145 | |
1146 * Check for SS.SSig | |
1147 | |
1148 NoS.Siz cmpa #SS.SSig | |
1149 bne NoS.Sig | |
1150 | |
1151 leax PD.Read,Y ;Point at read packet | |
1152 tst PM.Cpr,X ;Error if already somebody waiting | |
1153 bne NOTEOF | |
1154 | |
1155 * Set signal trap | |
1156 | |
1157 lda PD.CPR,Y ;Set process ID | |
1158 sta PM.CPR,X | |
1159 lda (R$X+1),U ;Get signal code | |
1160 sta PM.Sig,X | |
1161 tst PD.BCnt,Y ;Immediate signal if | |
1162 lbne SendSig | |
1163 | |
1164 bra QST.OK | |
1165 | |
1166 * Check for release of signal | |
1167 | |
1168 NoS.Sig cmpa #SS.Relea | |
1169 bne NoS.Rel | |
1170 | |
1171 leax PD.Read,Y ;Point at read packet | |
1172 lda PM.CPR,X | |
1173 cmpa PD.CPR,Y ;Our process set it? | |
1174 bne QST.OK | |
1175 | |
1176 * Release signal trap | |
1177 | |
1178 clrb | |
1179 lbra Switch | |
1180 | |
1181 * Not SS.Relea. Check for SS.Attr | |
1182 | |
1183 NoS.Rel cmpa #SS.Attr | |
1184 bne NoS.Atr | |
1185 | |
1186 * Change attributes if allowed | |
1187 | |
1188 ldx <D.Proc | |
1189 lda P$ID,X ;Are we superuser? | |
1190 beq SAT.OK | |
1191 tst PD.Own,Y ;Is creator still attached? | |
1192 bne SAT.XX | |
1193 | |
1194 sta PD.Own,Y ;Inherit pipe if owner abandoned it | |
1195 | |
1196 SAT.XX cmpa PD.Own,Y | |
1197 lbne FNAXit ;If can't match PID, E$FNA error | |
1198 | |
1199 * Change attributes. | |
1200 * Reg-U points at caller's registers | |
1201 | |
1202 SAT.OK lda R$A,U | |
1203 ora #(READ.+WRITE.) ;We insist . . . | |
1204 sta PD.MOD,Y | |
1205 bra QST.OK | |
1206 | |
1207 * Unknown SETSTT | |
1208 | |
1209 NoS.Atr lbra Unknown | |
1210 | |
1211 page | |
1212 * | |
1213 * Read CR-terminated line or element count from | |
1214 * pipe with no editing. Note that this call is | |
1215 * not well defined for element sizes other than | |
1216 * 1 byte. | |
1217 * | |
1218 | |
1219 READLN ldb PD.ESiz,Y | |
1220 decb | |
1221 bne RddEOF ;EOF error if more than 1 byte per element | |
1222 | |
1223 ldb #CR | |
1224 stb PD.REOR,Y | |
1225 bra READ001 | |
1226 | |
1227 * | |
1228 * Read element count from pipe with no editing. | |
1229 * | |
1230 * Note that if there are fewer elements in the pipe | |
1231 * than the user wants to read, and there are no writers | |
1232 * for the pipe, we return all elements followed by E$EOF. | |
1233 * | |
1234 | |
1235 READ clr PD.REOR,Y | |
1236 | |
1237 * Generic read. PD.REOR = terminator if non-null | |
1238 | |
1239 READ001 leax PD.Read,Y ;Get PID of reader (us) | |
1240 lbsr GETFREE | |
1241 bcs RddRTS | |
1242 | |
1243 ldd R$Y,U ;Desired element count | |
1244 beq RddXit | |
1245 | |
1246 * Set up for outer loop -- push zero element count | |
1247 * and space for buffer pointers on stack. | |
1248 | |
1249 clra | |
1250 clrb | |
1251 pshs D ;Initial count of elements read | |
1252 leas -4,S | |
1253 ldx R$X,U ;Initial buffer start address | |
1254 bra RddNext | |
1255 | |
1256 * Enter here to block on read. If there are no writers, | |
1257 * return E$EOF. | |
1258 | |
1259 CantRdd pshs X ;Save buffer pointer | |
1260 | |
1261 leax PD.Read,Y | |
1262 lbsr SigSlp | |
1263 lbcs RddDone | |
1264 | |
1265 * Inner loop to read bytes. | |
1266 * Here for initial attempt to read, | |
1267 * or to retry after blocking | |
1268 | |
1269 READOK ldx <D.PROC ;Point to our task descriptor | |
1270 ldb P$TASK,X ++LII | |
1271 puls X ++LII Recover current buffer pointer | |
1272 | |
1273 * Inner read loop. Read one element. | |
1274 * Note that we could use F$Move for elements larger | |
1275 * than 1 byte, because queue size is always an even | |
1276 * multiple of element size. | |
1277 | |
1278 RddMore lbsr DOREAD ;Get byte to A, or CS | |
1279 bcs CantRdd | |
1280 | |
1281 os9 F$STABX ;Put byte in caller's buffer | |
1282 leax 1,X | |
1283 tst PD.REOR,Y ;Is there an EOR character? | |
1284 beq NotRdLn | |
1285 | |
1286 cmpa PD.REOR,Y ;Did we match it? | |
1287 beq RddEOL | |
1288 | |
1289 NotRdLn cmpx 0,S ;Compare current addr. to end addr | |
1290 blo RddMore ; and loop until done | |
1291 | |
1292 * Done with element. Check for next. | |
1293 | |
1294 pshs X ;Save buffer pointer | |
1295 | |
1296 bsr CntDn ;Update queue count, etc | |
1297 cmpd R$Y,U ;Got all elements? | |
1298 bhs RddTail | |
1299 | |
1300 * Outer loop -- read one element at a time. | |
1301 * | |
1302 * X = next data pointer | |
1303 * Y = PD pointer | |
1304 | |
1305 RddNext stx 0,S ;Set new start address | |
1306 ldb PD.ESiz,Y ;Size of one element | |
1307 clra | |
1308 addd 0,S ;Compute end address of current element bfr | |
1309 std 2,S | |
1310 bra READOK ;Go to element reading loop | |
1311 | |
1312 * Read an EOL. Advance element count | |
1313 | |
1314 RddEOL pshs X ;Save buffer pointer | |
1315 bsr CntDn | |
1316 | |
1317 * Read everything, or aborting | |
1318 | |
1319 RddDone ldd 4,S ;Get element count | |
1320 | |
1321 * Tail end of read | |
1322 | |
1323 RddTail std R$Y,U | |
1324 leas 6,S ;Clean stack | |
1325 bne RddSome ;Success if read more than 0 elements | |
1326 | |
1327 * EOF error if no bytes read | |
1328 | |
1329 RddEOF comb | |
1330 ldb #E$EOF | |
1331 bra RddXit | |
1332 | |
1333 * Successful exit | |
1334 | |
1335 RddSome clrb | |
1336 | |
1337 RddXit leax PD.Read,Y | |
1338 lbra SWITCH | |
1339 | |
1340 * Decrement queued count, inc read count | |
1341 | |
1342 CntDn ldd #-1 | |
1343 bra CUpDn | |
1344 | |
1345 * Increment queued count, inc written count | |
1346 | |
1347 CntUp ldd #1 | |
1348 | |
1349 CUpDn addd PD.BCnt,Y ;Modify count of elements queued | |
1350 std PD.BCnt,Y | |
1351 | |
1352 * Bump I/O count | |
1353 | |
1354 IOCnt ldd (2+4),S ;Bump count of elements read/written | |
1355 addd #1 | |
1356 std (2+4),S | |
1357 RDDRTS rts | |
1358 | |
1359 page | |
1360 * | |
1361 * Write CR-terminated line or element count to | |
1362 * pipe with no editing | |
1363 * | |
1364 | |
1365 WRITELN ldb PD.ESiz,Y | |
1366 decb | |
1367 bne RddEOF ;EOF error if more than 1 byte per element | |
1368 | |
1369 ldb #CR | |
1370 stb PD.WEOR,Y | |
1371 bra Wrt001 | |
1372 | |
1373 * | |
1374 * Write byte count to pipe with no editing. | |
1375 * | |
1376 | |
1377 WRITE clr PD.WEOR,Y | |
1378 | |
1379 * Generic entry point | |
1380 | |
1381 Wrt001 leax PD.Writ,Y | |
1382 lbsr GETFREE ;Check I/O queue | |
1383 bcs WrtXit | |
1384 | |
1385 ldd R$Y,U ;Element count | |
1386 beq WrtXit | |
1387 | |
1388 * Set up for outer loop -- push zero element count | |
1389 * and space for buffer pointers on stack. | |
1390 | |
1391 clra | |
1392 clrb | |
1393 pshs D ;Initial count of elements read | |
1394 leas -4,S | |
1395 ldx R$X,U ;Initial buffer start address | |
1396 bra WrtNext | |
1397 | |
1398 * Enter here to block on write | |
1399 | |
1400 CantWrt pshs X | |
1401 | |
1402 leax PD.Writ,Y | |
1403 lbsr SigSlp | |
1404 bcs WrtErr | |
1405 | |
1406 * Begin (or resume) write | |
1407 | |
1408 WRITOK ldx <D.PROC ++LII | |
1409 ldb P$TASK,X ;Get our DAT image # | |
1410 puls X ++LII | |
1411 | |
1412 * Main write loop | |
1413 | |
1414 WrtMore os9 F$LDABX ;Get a byte from caller's buffer | |
1415 lbsr DOWRITE | |
1416 bcs CantWrt | |
1417 | |
1418 leax 1,X | |
1419 tst PD.WEOR,Y ;EOL character defined? | |
1420 beq NotWrLn | |
1421 | |
1422 cmpa PD.WEOR,Y | |
1423 beq WrtEOL | |
1424 | |
1425 * See if at end of buffer | |
1426 | |
1427 NotWrLn cmpx 0,S | |
1428 blo WrtMore | |
1429 | |
1430 * Done with element. Check for next. | |
1431 | |
1432 pshs X ;Save buffer pointer | |
1433 | |
1434 bsr CntUp | |
1435 cmpd R$Y,U ;Put all elements? | |
1436 bhs WrtTail | |
1437 | |
1438 * Outer loop -- write one element at a time. | |
1439 | |
1440 WrtNext stx 0,S ;Set new start address | |
1441 ldb PD.ESiz,Y ;Size of one element | |
1442 clra | |
1443 addd 0,S ;Compute end address of current element bfr | |
1444 std 2,S | |
1445 bra WRITOK ;Go to element reading loop | |
1446 | |
1447 * Wrote an EOL. Advance element count | |
1448 | |
1449 WrtEOL pshs X ;Save buffer pointer | |
1450 bsr CntUp | |
1451 | |
1452 * Wrote everything, or aborting | |
1453 | |
1454 WrtDone ldd 4,S ;Get element count | |
1455 | |
1456 * Tail end of write | |
1457 | |
1458 WrtTail std R$Y,U | |
1459 leas 6,S ;Clean stack | |
1460 | |
1461 * Successful exit | |
1462 | |
1463 WrtSome clrb | |
1464 | |
1465 WrtXit leax PD.Writ,Y | |
1466 bra SWITCH | |
1467 | |
1468 * Error exit | |
1469 | |
1470 WrtErr pshs B | |
1471 ldd (4+1),S | |
1472 std R$Y,U | |
1473 puls B | |
1474 | |
1475 leas 6,S | |
1476 bra WrtXit | |
1477 | |
1478 page | |
1479 * | |
1480 * I/O queue manipulation routines | |
1481 * | |
1482 | |
1483 GETFREE lda PM.CPR,X ;Is any process using this resource? | |
1484 beq SETPMCPR ; (branch if not) | |
1485 | |
1486 cmpa PD.CPR,Y ;Does caller control this resource? | |
1487 beq OURDEVIC ; (branch if so) | |
1488 | |
1489 inc PM.CNT,X ;Bump # of active r/w images | |
1490 ldb PM.CNT,X | |
1491 cmpb PD.CNT,Y ;See if equal to # of open images | |
1492 bne SETQUEUE ; (if not, run everybody else to free it) | |
1493 | |
1494 lbsr SENDSIG ;Yes -- wake up next process | |
1495 | |
1496 * Process number in Reg-A | |
1497 * Put the process into the I/O queue and | |
1498 * sleep until a signal wakes us up | |
1499 | |
1500 SETQUEUE os9 F$IOQU | |
1501 dec PM.CNT,X ;Caller is asleep, so 1 less active | |
1502 pshs X | |
1503 ldx <D.PROC | |
1504 ldb P$SIGNAL,X ;Get caller's signal | |
1505 puls X | |
1506 beq GETFREE ;Loop until there's a signal | |
1507 | |
1508 coma ;Error if caller is waiting | |
1509 rts | |
1510 | |
1511 * Nobody using the resource. Grab it. | |
1512 | |
1513 SETPMCPR ldb PD.CPR,Y | |
1514 stb PM.CPR,X ;Make caller "owner" | |
1515 | |
1516 * Exit -- caller owns the pipe | |
1517 | |
1518 OURDEVIC clrb | |
1519 rts | |
1520 | |
1521 * | |
1522 * Set a wakeup signal for the calling process | |
1523 * | |
1524 | |
1525 SigSlp ldb PM.CNT,X ;Active image count | |
1526 incb | |
1527 cmpb PD.CNT,Y ;Everybody active? | |
1528 bne SgSlp01 ; (if not, try sending signals) | |
1529 | |
1530 * Nobody on the other end to signal. | |
1531 * Error if anonymous, else hang out a bit. | |
1532 | |
1533 tst PD.Name,Y ;If anonymous pipe & nobody left, error | |
1534 beq WRITEROR | |
1535 | |
1536 * Named pipe and nobody to signal. Not an error if data in pipe. | |
1537 | |
1538 tst PD.BCnt,Y ;Number of items in pipe | |
1539 beq WRITEROR | |
1540 | |
1541 * Send signal to other end of pipe (may not be one, though) | |
1542 | |
1543 SgSlp01 stb PM.CNT,X | |
1544 ldb #S$WAKE | |
1545 stb PM.SIG,X ;Force caller's signal to "wakeup" | |
1546 clr PD.CPR,Y | |
1547 pshs X | |
1548 tfr X,D ;Switch from reader to writer or vis-a-vis | |
1549 eorb #4 | |
1550 tfr D,X | |
1551 lbsr SENDSIG ;Send signal to opposite end of pipe | |
1552 ldx #0 | |
1553 os9 F$SLEEP ;Caller sleeps until signaled | |
1554 ldx <D.PROC | |
1555 ldb P$SIGNAL,X | |
1556 puls X | |
1557 dec PM.CNT,X ;Caller is asleep, so 1 less active | |
1558 tstb | |
1559 bne GOTSIGNL ;Error if opposite end set no signal | |
1560 | |
1561 clrb | |
1562 rts | |
1563 | |
1564 * WRITE ERROR hook | |
1565 | |
1566 WRITEROR ldb #E$WRITE | |
1567 | |
1568 * Generic error hook | |
1569 | |
1570 GOTSIGNL coma | |
1571 rts | |
1572 | |
1573 * | |
1574 * Release this end of the pipe, and | |
1575 * send a signal to the other end. | |
1576 * | |
1577 * Enter pointing to variables for | |
1578 * this end; exit pointing to variables | |
1579 * for opposite end. | |
1580 * | |
1581 | |
1582 SWITCH pshs CC,B,U | |
1583 clr PM.CPR,X ;No process controlling current end | |
1584 tfr X,D | |
1585 eorb #4 ;Switch to other end (MAGIC) | |
1586 tfr D,X | |
1587 lbsr SENDSIG ;Awaken other end | |
1588 puls CC,B,U,PC | |
1589 | |
1590 * | |
1591 * Write one byte to queue described in path | |
1592 * descriptor. Return CS if queue full. | |
1593 * Doesn't update count of ELEMENTS queued. | |
1594 * | |
1595 | |
1596 DOWRITE pshs B,X | |
1597 ldx PD.NxtI,Y | |
1598 ldb PD.RFlg,Y | |
1599 beq SETREADY ;(say data available) | |
1600 | |
1601 cmpx PD.NxtO,Y | |
1602 bne STORDATA ;(branch if queue not full) | |
1603 | |
1604 * Error -- queue is full | |
1605 | |
1606 comb | |
1607 puls B,X,PC | |
1608 | |
1609 * Mark data available in queue | |
1610 | |
1611 SETREADY ldb #1 | |
1612 stb PD.RFlg,Y | |
1613 | |
1614 * Put data in Reg-A into queue, and advance | |
1615 * pointer to next in w/ wrap | |
1616 | |
1617 STORDATA sta ,X+ | |
1618 cmpx PD.End,Y | |
1619 blo WTNOWRAP | |
1620 | |
1621 ldx PD.BUF,Y | |
1622 leax PP.Data,X | |
1623 | |
1624 WTNOWRAP stx PD.NxtI,Y | |
1625 | |
1626 * Don't step Character Input Counter. | |
1627 | |
1628 clr PD.Wrtn,Y | |
1629 puls B,X,PC | |
1630 | |
1631 * | |
1632 * Read one byte from queue described in path | |
1633 * descriptor. Return CS if none available. | |
1634 * Doesn't update count of ELEMENTS queued. | |
1635 * | |
1636 | |
1637 DOREAD lda PD.RFlg,Y ;Any data? | |
1638 bne DATAREDY | |
1639 | |
1640 * No data -- return CS | |
1641 | |
1642 comb | |
1643 rts | |
1644 | |
1645 * Get data from queue | |
1646 | |
1647 DATAREDY pshs X | |
1648 ldx PD.NxtO,Y ;Get next out pointer | |
1649 lda ,X+ | |
1650 cmpx PD.End,Y | |
1651 blo RDNOWRAP | |
1652 | |
1653 ldx PD.BUF,Y | |
1654 leax PP.Data,X | |
1655 | |
1656 * Save updated next out pointer | |
1657 | |
1658 RDNOWRAP stx PD.NxtO,Y | |
1659 cmpx PD.NxtI,Y | |
1660 bne NOTEMPTY | |
1661 | |
1662 clr PD.RFlg,Y ;Mark queue empty | |
1663 | |
1664 * Don't decrement Character Input Counter. | |
1665 | |
1666 NOTEMPTY equ * | |
1667 | |
1668 * Exit with character in Reg-A | |
1669 | |
1670 andcc #NCARRY ;Clear carry | |
1671 puls X,PC | |
1672 | |
1673 page | |
1674 * | |
1675 * Utility placed here to not make assembly listing obsolete. | |
1676 * | |
1677 | |
1678 MovSet os9 F$Move ;Do inter-process block move | |
1679 | |
1680 * Force set MSB at end of name | |
1681 | |
1682 tfr Y,D ;Byte count to D | |
1683 decb | |
1684 lda B,U ;Get last byte of name | |
1685 ora #%10000000 | |
1686 sta B,U | |
1687 | |
1688 rts | |
1689 | |
1690 ifeq (PIPEDIR-YESDIR) | |
1691 | |
1692 * | |
1693 * Find out how many pipes there are for the | |
1694 * current device, and set up device descriptor | |
1695 * so that pipe buffer will hold 32 bytes of | |
1696 * data for each. | |
1697 * | |
1698 * Reg-Y = PD pointer | |
1699 * | |
1700 * Exit with size set up in PD. | |
1701 * CC=EQ if no pipes. | |
1702 * | |
1703 | |
1704 SizDirP pshs X,D | |
1705 | |
1706 clrb ;Clear count of pipes | |
1707 ldx PD.Dev,Y | |
1708 ldx V$Stat,X ;Point at static storage | |
1709 ldx V.List,X ;Get head of linked list | |
1710 beq GotCnt | |
1711 | |
1712 * There are some pipes. Count them. | |
1713 | |
1714 PCount incb | |
1715 ldx PP.Next,X ;Track down linked list | |
1716 bne PCount | |
1717 | |
1718 * Now Reg-B = pipe count. Need 32 bytes per pipe. | |
1719 | |
1720 GotCnt incb ;Add one for us! | |
1721 lda #32 | |
1722 mul | |
1723 std PD.QSiz,Y ;Set element count for this pipe | |
1724 lda #1 | |
1725 sta PD.ESiz,Y ;Set element size to 1 byte | |
1726 | |
1727 puls D,X,PC | |
1728 | |
1729 * | |
1730 * Fill pipe buffer with directory data. | |
1731 * | |
1732 * The data is organized like an RBF directory: | |
1733 * | |
1734 * Offset Data | |
1735 * -------- -------------------------------- | |
1736 * $00-$1C Pipe name | |
1737 * $1D DAT task number of pipe buffer | |
1738 * $1E-$1F Address of pipe buffer in task | |
1739 * | |
1740 * | |
1741 FilDirP pshs U,X,D | |
1742 | |
1743 ldx PD.Dev,Y | |
1744 ldx V$Stat,X ;Point at static storage | |
1745 ldx V.List,X ;Get head of linked list | |
1746 beq GotFil | |
1747 | |
1748 * Write data for pipe buffer @X to pipe with PD @Y | |
1749 | |
1750 FD000 ldu PP.PD,X ;Point at PD for pipe to be dumped | |
1751 leau PD.Name,u | |
1752 ldb #NameMax | |
1753 | |
1754 FD001 lda ,u+ ;Write pipe name | |
1755 bsr QWrite | |
1756 decb | |
1757 bne FD001 | |
1758 | |
1759 ldu <D.SysPrc ;Get system DAT image number | |
1760 lda P$Task,u | |
1761 bsr QWrite | |
1762 | |
1763 pshs X ;Get pipe buffer pointer | |
1764 lda ,S+ | |
1765 bsr QWrite | |
1766 lda ,S+ | |
1767 bsr QWrite | |
1768 | |
1769 * Advance to next pipe buffer | |
1770 | |
1771 ldx PP.Next,X | |
1772 bne FD000 | |
1773 | |
1774 * All done. Restore regs & exit | |
1775 | |
1776 GotFil puls D,X,U,PC | |
1777 | |
1778 * Byte saver | |
1779 | |
1780 QWrite lbra DoWrite | |
1781 | |
1782 * | |
1783 * Immortal entry point | |
1784 * | |
1785 Immort coma | |
1786 sbcb #38 | |
1787 lsrb | |
1788 fcb $42 ;SBCB op-code | |
1789 | |
1790 * Fall through to SS.FD processing | |
1791 | |
1792 * | |
1793 * Routine to process SS.FD call on an open pipe. | |
1794 * Creates a pseudo-FD in the user's buffer (@R$X). | |
1795 * Desired byte count in R$Y. | |
1796 * | |
1797 * The pseudo-file descriptor sector includes the following: | |
1798 * | |
1799 * Offset Description | |
1800 * -------- -------------------------------------- | |
1801 * $00 Attributes | |
1802 * $01-$02 Owner's *PROCESS* ID | |
1803 * $03-$07 Zeros (date of last access) | |
1804 * $08 Use count | |
1805 * $09-$0C Number of items queued | |
1806 * $0D-$0F Zeros (creation date) | |
1807 * $10-$FF Zeros (segment list -- at least 5 zeros needed) | |
1808 * | |
1809 | |
1810 DoSSFD pshs D,X,Y,U | |
1811 | |
1812 ldb #(16+5) ;Clear data on stack | |
1813 SSFD01 clr ,-S | |
1814 decb | |
1815 bne SSFD01 | |
1816 | |
1817 * Set attributes | |
1818 lda PD.Mod,Y | |
1819 sta FD.ATT,S | |
1820 | |
1821 * Set owner's process ID | |
1822 lda PD.Own,Y | |
1823 sta (FD.OWN+1),S | |
1824 | |
1825 * Set use count | |
1826 lda PD.CNT,Y | |
1827 sta FD.LNK,S | |
1828 | |
1829 * Set queue count | |
1830 | |
1831 ldd PD.BCNT,Y | |
1832 std (FD.SIZ+2),S | |
1833 | |
1834 * Now copy the data into the caller's buffer | |
1835 | |
1836 ldx <D.SysPrc ;Pointer to our PD | |
1837 lda P$Task,X ; get system's DAT image # (source) | |
1838 ldx <D.Proc ;Pointer to caller's PD | |
1839 ldb P$Task,X ; get caller's DAT image # (dest) | |
1840 ldy R$Y,U ;Byte count | |
1841 leax 0,S ;Source address | |
1842 ldu R$X,U ;Destination address | |
1843 os9 F$Move ;Do the move | |
1844 | |
1845 * All done. | |
1846 | |
1847 leas (16+5),S | |
1848 puls U,X,Y,D,PC | |
1849 | |
1850 endc | |
1851 | |
1852 emod | |
1853 | |
1854 MODSIZE equ * | |
1855 | |
1856 end | |
1857 |