|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: File: DriverServices.c
27:
28: Contains: Native Driver support code for Device Manager
29:
30: Version: xxx put version here xxx
31:
32: Written by: Tom Saulpaugh
33:
34: Copyright: � 1994-1997 by Apple Computer, Inc., all rights reserved.
35:
36: File Ownership:
37:
38: DRI: xxx put dri here xxx
39:
40: Other Contact: xxx put other contact here xxx
41:
42: Technology: xxx put technology here xxx
43:
44: Writers:
45:
46: (JM3) Jim Murphy
47: (CSS) Chas Spillar
48: (KW) Kevin Williams
49: (MRN) Matthew Nelson
50:
51: Change History (most recent first):
52:
53: <63> 18-Jun-97 JM3 Updated for cleaned up NanoKernelPriv/PPCInfoRecordsPriv.
54: <62> 5/30/97 CSS Delay() now takes an unsigned long * instead of a long * as its
55: second parameter.
56: <61> 3/18/97 KW DelayFor Hardware was just looking at 5FFF EF80 to get the
57: Processor Info structure. Now use the pointer located at
58: ProcessorInfo Ptr to get the pointer to the structure
59: <60> 8/6/96 MRN Changes to stop using private copy of 64 bit math routines and
60: instead link against the real shipping version of the Math64Lib.
61: <59> 10/30/95 MRN Get rid of C version of SynchronizeIO that moved to
62: DriverServices.s, and make file buildable with MrC.
63: <58> 4/15/95 tjm #1238020 - Fix DelayForHardware to handle 601 correctly. Moved
64: fix back into DSL.m4
65: <57> 4/14/95 tjm #1238020 - Fix DelayForHardware to handle 601 correctly.
66: <56> 4/10/95 TS Fix bug in PBEnqueueLast
67: <55> 4/10/95 TS Optimize PBEnqueueLast for a queue of 1 or less elements
68: <54> 4/6/95 TS Fix PBDequeue
69: <53> 4/5/95 TS Rewrite PBEnqueueLast (Bug #1236338)
70: <52> 3/31/95 TS Bump preallocated data numbers and comment out debugging names
71: before ROM freezes.
72: <51> 3/30/95 TS Retry CompareAndSwap in PBDequeue if element is at head of queue
73: <50> 3/30/95 TS Add OSTypes to each Globals Struct and reserve some space here
74: as well.
75: <49> 3/29/95 TS Return last element in PBDequeueLast (Optimized path)
76: <48> 3/28/95 TS Optimize PBDequeue and PBDequeueLast for the first element
77: <47> 3/27/95 TS Fix bug #1232734 (IOCommandIsComplete return value)
78: <46> 3/22/95 TS Optimize fix for bug #1228034
79: <45> 3/14/95 tjm #1227300 - Insure that PStrNCmp works with all equal strings.
80: <44> 3/14/95 tjm #1228034 - insure that queueing functions are safe from
81: interrupts
82: <43> 2/21/95 tjm #1220575 - Correct PStrNCat to handle strings > 255.
83: <42> 2/20/95 tjm #1220560 - Fix PStrCat to correctly handle dest strings > 128.
84: <41> 1/27/95 tjm #1214980 - PStrNCmp does not return correct value with null
85: strings.
86: <40> 1/25/95 tjm #1214207 - Fix PBDequeueLast to delete if only one item in
87: queue.
88: <39> 1/25/95 tjm #1214730 - Fix PStrCat to only Cat up to 255 chars.
89: <38> 1/19/95 tjm Break out DSLInit routine to aid in debugging
90: <37> 1/19/95 tjm #1211193 - Allow Dequeuing from head.
91: <36> 1/18/95 tjm #1212320 - Insure PBEnqueueLast is re-entrant.
92: <35> 1/18/95 tjm #1203060 - Make a Global Data Lib for the DSL.
93: <34> 1/16/95 tjm #1203145 - Add DelayForHardware so drivers can call delay
94: routine at InterruptTime.
95: <33> 1/10/95 tjm #1210156 - Make sure PBQueueDelete correctly deallocated
96: preallocated qHdrs.
97: <32> 1/10/95 tjm #1210154 - return noErr for unaligned qHdr allocation.
98: <31> 1/10/95 tjm #1207351 - Make sure PStrLen returns correct value.
99: <30> 1/10/95 tjm #1207081 - Fix the PStr functions to handle lengths correctly
100: <29> 1/9/95 tjm #1208049 - return paramErr if CSI fails.
101: <28> 1/9/95 tjm #1209423 - correctly handle empty qHdr when it is empty
102: <27> 1/9/95 MN Add a call to UpTime in the CFM initialization function to
103: initialize the timebase variable in the new timing functions.
104: <26> 12/21/94 MN Restore checkins 18 through 24 and include the fixes checked
105: into 25.
106: <25> 12/21/94 MN Added alignment support to PBQueueCreate and PBQueueDelete for Marconi_v16c2
107: which would have checked in over the top of checkins 18 through 24.
108: <24> 12/20/94 tjm #1206624 - Fix PBDequeueLastSync to correctly dequeue item.
109: <23> 12/19/94 tjm #1204196 - fix this again.
110: <22> 12/16/94 tjm #1206622 - eliminate reentrantcy problem with PBDequeueSync.
111: <21> 12/16/94 tjm #1203051 - added PBEnqueueLast function
112: <20> 12/15/94 tjm #1204196 - call PBQueueInit when PBQueueCreate is successful.
113: <19> 12/15/94 tjm #1204193 - initialize qFlags in qHeader of PBQueueInit.
114: <18> 12/15/94 tjm #1203057 - increment the number of SWI's to 32
115: <17> 12/5/94 tjm #1202888 - Fix PBDequeue to not corrupt queue with 2 elements
116: <16> 12/5/94 tjm #1202776 - Fix PBDequeue to return qErr for nonexistant element.
117: <15> 12/5/94 tjm #1201314 - correctly queue secondary interrupts
118: <14> 11/15/94 tjm #1195428 - Fix function prototypes to correctly define src ptrs
119: as const.
120: <13> 11/3/94 tjm fix DelayFor to use low end of 64 bit divide, ID#1197350
121: <12> 10/25/94 tjm Call TimerInitialize, SIHInitialize, and MemoryInitialze to fix
122: #1192590
123: <11> 9/15/94 MN Add call in DSL_Init to startup Interrupt Manager and change
124: PBQueueInit to return an error code;
125: <10> 8/31/94 TS Make the DSL_Init check for failures
126: <9> 8/29/94 TS Add a call to the CFM init routine to calculate physical RAM
127: size using the ROM physical space table
128: <8> 8/25/94 TS Add DelayFor and Move BlockCopy to MemoryManagement.c
129: <7> 8/24/94 TS Add in checks for correct execution levels
130: <6> 8/24/94 TS Make DSL_Init return noErr to library will load
131: <5> 8/24/94 TS Build ExecutionLevel Func
132: <4> 8/23/94 TS Implement SoftwareInterrupts
133: <3> 8/18/94 TS Add more queue functions
134: <2> 8/17/94 JF Changes from PCI developer kitchen
135: <1> 8/5/94 JF first checked in
136:
137: */
138:
139:
140:
141: //
142: // Source to the NuDriver Support Services Library
143: //
144:
145: //#include <Types.h>
146: //#include <Strings.h>
147: //#include <Files.h>
148: //#include <MixedMode.h>
149: //#include <LowMem.h>
150: //#include <Math64.h>
151:
152: // Get Prototypes of the Exported Services First,...
153:
154: #include "driverservices.h"
155: #include "driverservicespriv.h"
156: #include "PPCInfoRecordsPriv.h"
157: #include "rhap_local.h"
158:
159: // The Driver Services Follow,...
160:
161:
162: OSErr InitSwis (void);
163:
164: /////////////////////////////////////////////////////////////////////////////////
165: //
166: // Command Processing
167: //
168: //
169:
170: /*-------------------------------------------------------------------------------
171:
172: Routine: IOCommandIsComplete - Marks I/O Command as Done.
173:
174: Function: Returns IODone result from Device Manager
175:
176: Input: theID - ID of the in-progress I/O command.
177: theResult - the result value of the command. (Low 16-bits are placed in IOPB)
178:
179: Result: noErr or
180: -------------------------------------------------------------------------------*/
181: /*naga
182: enum {
183: uppIODoneProcInfo = kRegisterBased
184: | REGISTER_ROUTINE_PARAMETER(1,kRegisterA1,kFourByteCode)
185: | REGISTER_ROUTINE_PARAMETER(2,kRegisterD0,kFourByteCode)
186: };
187:
188:
189: OSErr IOCommandIsComplete ( IOCommandID theID,
190: OSErr theResult)
191: {
192: ParmBlkPtr The_Pb = (ParmBlkPtr)theID;
193: OSErr *The_Result = (OSErr *)(&The_Pb -> ioParam.ioCmdAddr);
194:
195: if (theID == nil)
196: return paramErr;
197:
198: *The_Result = theResult;
199:
200: (void)CallUniversalProc ( LMGetJIODone(),
201: uppIODoneProcInfo,
202: The_Pb,
203: 1 );
204: return noErr;
205: }
206: naga */
207: /*-------------------------------------------------------------------------------
208:
209: Routine: GetIOCommandInfo - Returns info about an in-progress I/O command.
210:
211: Function: Returns IOCommandContents, IOCommandCode, and IOCommandKind.
212:
213: Input: theID - ID of the in-progress I/O command.
214:
215: Output: theContents - pointer to the IOPB or Initialize/Finalize Contents.
216: theCommand - the command code
217: theKind - the kind of I/O (Sync, Async, or Immed)
218:
219: Result: noErr
220: -------------------------------------------------------------------------------*/
221: /*naga
222: OSErr GetIOCommandInfo ( IOCommandID theID,
223: IOCommandContents * theContents,
224: IOCommandCode * theCommand,
225: IOCommandKind * theKind )
226: {
227: IOCommandContents The_Contents;
228: ParmBlkPtr The_Pb = (ParmBlkPtr)theID;
229:
230: if (theID == nil)
231: return paramErr;
232:
233: The_Contents . pb = The_Pb;
234:
235: *theContents = The_Contents;
236: *theCommand = (The_Pb -> ioParam.ioTrap & 0x00ff);
237: *theKind = ((The_Pb -> ioParam.ioTrap & 0xff00) >> 8);
238:
239: return noErr;
240: }
241: */
242:
243: /////////////////////////////////////////////////////////////////////////////////
244: //
245: // Queues
246: //
247: //
248:
249: /*-------------------------------------------------------------------------------
250:
251: Routine: PBQueueInit - Initialize a Queue (@ NON-Interrupt-lvl and SIH-lvl)
252:
253: -------------------------------------------------------------------------------*/
254:
255: OSErr PBQueueInit(QHdrPtr qHeader)
256: {
257: qHeader -> qHead = nil;
258: qHeader -> qTail = nil;
259: qHeader -> qFlags = 0x0000;
260:
261: return noErr;
262: }
263:
264: /*-------------------------------------------------------------------------------
265:
266: Routine: PBQueueCreate - Initialize a Queue (@ NON-Interrupt lvl)
267:
268: -------------------------------------------------------------------------------*/
269:
270: OSErr PBQueueCreate(QHdrPtr *qHeader)
271: {
272: Ptr **theQueue;
273:
274: if (CurrentExecutionLevel() != kTaskLevel)
275: {
276: // SysDebugStr ((StringPtr)"\pPBQueueCreate not called at Task Level!");
277: // 11/30/98 Adam return -1;
278: }
279:
280: *qHeader = nil;
281: theQueue = (Ptr **)PoolAllocateResident (sizeof(QHdr)+sizeof(short)+sizeof(Ptr),true);
282: if (theQueue != nil)
283: {
284: // Store orig ptr in first 4 bytes.
285: *theQueue = (Ptr *)theQueue;
286: theQueue++;
287:
288: // Are we not aligned?
289: if ( ((UInt32)theQueue & 3) == 0 )
290: {
291: short *pattern = (short *)theQueue;
292:
293: *pattern++ = 0x4D4E;
294: *qHeader = (QHdrPtr)pattern;
295: return noErr;
296: }
297: else
298: {
299: *qHeader = (QHdrPtr)theQueue;
300: return noErr;
301: }
302: }
303: else
304: return mFulErr;
305: }
306:
307: /*-------------------------------------------------------------------------------
308:
309: Routine: PBQueueDelete - Finalize a Queue (@ NON-Interrupt lvl)
310:
311: -------------------------------------------------------------------------------*/
312:
313: OSErr PBQueueDelete(QHdrPtr qHeader)
314: {
315: Ptr **theMemory;
316: UInt16 *pattern = (UInt16 *)qHeader;
317:
318: if (CurrentExecutionLevel() != kTaskLevel)
319: {
320: // SysDebugStr ((StringPtr)"\pPBQueueDelete not called at Task Level!");
321: return -1;
322: }
323:
324: if (*--pattern == 0x4D4E)
325: qHeader = (QHdrPtr)((UInt32)(qHeader) - sizeof(UInt16));
326:
327: theMemory = (Ptr **)qHeader;
328: theMemory--;
329:
330: if (*theMemory != (Ptr *)theMemory)
331: {
332: // SysDebugStr ((StringPtr)"\pPBQueueDelete not a Queue Header!");
333: return -1;
334: }
335:
336: (void)PoolDeallocate(theMemory);
337: return noErr;
338: }
339:
340: /*-------------------------------------------------------------------------------
341:
342: Routine: PBEnqueueLast - Add an IOPB to the end of a Request Queue. (@ Any Exec-lvl)
343: (Optimized for queue size of 1 or less)
344:
345: -------------------------------------------------------------------------------*/
346:
347: OSErr PBEnqueueLast(QElemPtr qElement, QHdrPtr qHeader)
348: {
349: QElemPtr currElemPtr;
350: UInt16 sr;
351:
352: // New element will be at end of queue.
353: qElement -> qLink = nil;
354:
355: // Currently an empty queue?
356: while ( qHeader -> qHead == nil )
357: {
358: if (CompareAndSwap ((UInt32) nil, (UInt32) qElement, (UInt32 *) &qHeader->qHead))
359: return noErr;
360: }
361:
362: // Multi-element queue,...
363:
364: // Do it the sure, but slow way.
365: sr = Disable68kInterrupts();
366:
367: // Entire queue empty?
368: if ( qHeader -> qHead == nil )
369: {
370: // Add at head of queue
371: qHeader -> qHead = qElement;
372: }
373: else
374: {
375: // Else, Get first element in queue.
376: currElemPtr = (QElemPtr)qHeader->qHead;
377:
378: // Move toward the end of the queue,...
379: while ( currElemPtr -> qLink != nil )
380: {
381: currElemPtr = currElemPtr -> qLink;
382: }
383:
384: currElemPtr -> qLink = qElement;
385: }
386:
387: Restore68kInterrupts(sr);
388: return noErr;
389: }
390:
391: /*-------------------------------------------------------------------------------
392:
393: Routine: PBEnqueue - Add an IOPB to Head of Request Queue. (@ Any Exec-lvl)
394:
395: Function: Returns (nothing)
396:
397: Result: void
398: -------------------------------------------------------------------------------*/
399:
400: void PBEnqueue(QElemPtr qElement, QHdrPtr qHeader)
401: {
402: do {
403: qElement -> qLink = qHeader->qHead;
404: } while (CompareAndSwap ((UInt32) qElement->qLink, (UInt32) qElement,
405: (UInt32 *) &qHeader->qHead) == false);
406: }
407:
408:
409: /*-------------------------------------------------------------------------------
410:
411: Routine: PBDequeue - Remove an IOPB from a Request Queue. (@ Any Exec-lvl)
412:
413: Function: Returns (nothing)
414:
415: Result: void
416: -------------------------------------------------------------------------------*/
417:
418: static OSErr PBDequeueSync(QElemPtr qElement, QHdrPtr qHeader)
419: {
420: QElemPtr prevElemPtr, currElemPtr;
421: OSErr result = noErr;
422: UInt16 sr;
423:
424: // Validate params.
425: if ( (qElement == nil) || (qHeader == nil) )
426: return paramErr;
427:
428: sr = Disable68kInterrupts();
429:
430: currElemPtr = (QElemPtr)qHeader->qHead;
431: prevElemPtr = nil;
432:
433: // Find the one we want.
434: while ( currElemPtr && (currElemPtr != qElement) )
435: {
436: // Advance the cause.
437: prevElemPtr = currElemPtr;
438: currElemPtr = currElemPtr -> qLink;
439: }
440:
441: // We find it?
442: if ( currElemPtr )
443: {
444: // Middle of the queue somewhere?
445: if ( prevElemPtr )
446: prevElemPtr -> qLink = currElemPtr ->qLink;
447: else
448: qHeader->qHead = currElemPtr ->qLink;
449:
450: currElemPtr -> qLink = nil;
451: }
452: else
453: result = qErr; // not on the list.
454:
455: Restore68kInterrupts(sr);
456: return result;
457: }
458:
459:
460: OSErr PBDequeue(QElemPtr qElement, QHdrPtr qHeader)
461: {
462: // Optimize for common case of 1 element on the queue.
463:
464: // First one on the queue?
465: while ( qHeader -> qHead == qElement )
466: {
467: // If the element is still at the head of the queue,... Remove it, and we are done.
468: if (CompareAndSwap ((UInt32) qElement,
469: (UInt32) qElement -> qLink,
470: (UInt32 *) &qHeader->qHead) == true)
471: {
472: qElement -> qLink = nil;
473:
474: return noErr;
475: }
476: }
477:
478: // Multiple elements on the queue.
479: return PBDequeueSync (qElement, qHeader);
480: }
481:
482: /*-------------------------------------------------------------------------------
483:
484: Routine: PBDequeueFirst - Remove First Element on a Queue (@ Any Exec-lvl)
485:
486: Result: noErr or qErr
487: -------------------------------------------------------------------------------*/
488:
489: OSErr PBDequeueFirst(QHdrPtr qHeader, QElemPtr *theFirstqElem)
490: {
491: QElemPtr qElement;
492:
493: do {
494: // Get Queue Head Ptr
495: qElement = qHeader -> qHead;
496:
497: // Empty Queue?
498: if ( qElement == nil )
499: {
500: if ( theFirstqElem )
501: *theFirstqElem = nil;
502:
503: return qErr;
504: }
505:
506: // If the element is still at the head of the queue,... Remove it, and we are done.
507: if (CompareAndSwap ((UInt32) qElement,
508: (UInt32) qElement -> qLink,
509: (UInt32 *) &qHeader->qHead) == true)
510: {
511: if ( theFirstqElem )
512: *theFirstqElem = qElement;
513:
514: qElement -> qLink = nil;
515:
516: return noErr;
517: }
518: } while (1);
519: }
520:
521: /*-------------------------------------------------------------------------------
522:
523: Routine: PBDequeueLast - Remove Last Element on a Queue (@ Any Exec-lvl)
524:
525: Result: noErr or qErr
526: -------------------------------------------------------------------------------*/
527:
528: OSErr PBDequeueLast(QHdrPtr qHeader, QElemPtr *theLastqElem)
529: {
530: QElemPtr currElemPtr, prevElemPtr;
531: OSErr result = noErr;
532: UInt16 sr;
533:
534: if ( theLastqElem )
535: *theLastqElem = nil;
536:
537: sr = Disable68kInterrupts();
538:
539: // Get Queue Head Ptr and our initial previous ptr
540: if ((prevElemPtr = qHeader -> qHead) == nil)
541: result = qErr; // q is empty
542: else
543: {
544: // Get head of queue
545: currElemPtr = (QElemPtr)qHeader->qHead;
546:
547: // Move toward the end of the queue,...
548: while ( currElemPtr -> qLink != nil )
549: {
550: prevElemPtr = currElemPtr;
551: currElemPtr = currElemPtr ->qLink;
552: }
553:
554: // Remove last one from the queue.
555: prevElemPtr->qLink = nil;
556:
557: // If last was also the first, nil out qheader.
558: if ( currElemPtr == qHeader -> qHead )
559: qHeader -> qHead = nil;
560:
561: // Return last element to caller.
562: if ( theLastqElem )
563: *theLastqElem = currElemPtr;
564: }
565:
566: Restore68kInterrupts(sr);
567: return result;
568: }
569:
570: /////////////////////////////////////////////////////////////////////////////////
571: //
572: // Strings
573: //
574: //
575:
576: /*-------------------------------------------------------------------------------
577:
578: Routine: CStrCopy - Copy string of chars from src to dst.
579:
580: Function: Copies characters upto and including the null character from 'src' to
581: 'dst' char strings.
582:
583: Note: This routine assumes the two strings do not overlap. It would be bad.
584:
585: Input: src - pointer to the source string of char's to copy.
586:
587: Output: dst - pointer to the destination string of char's.
588:
589: Result: dst - a pointer to the destination string is returned.
590: -------------------------------------------------------------------------------*/
591:
592: char *CStrCopy (char *dst, const char *src)
593: {
594: char *pos = dst;
595:
596: while ( (*pos++ = *src++) != 0) // copy src to dst
597: ;
598:
599: return dst;
600: }
601:
602:
603: /*-------------------------------------------------------------------------------
604:
605: Routine: PStrCopy - Copy string of chars from src to dst.
606:
607: Function: Copies characters upto and including the null character from 'src' to
608: 'dst' char strings.
609:
610: Note: This routine assumes the two strings do not overlap. It would be bad.
611:
612: Input: src - pointer to the source string of char's to copy.
613:
614: Output: dst - pointer to the destination string of char's.
615:
616: Result: dst - a pointer to the destination string is returned.
617: -------------------------------------------------------------------------------*/
618:
619: StringPtr PStrCopy (StringPtr dst, ConstStr255Param src)
620: {
621: UInt8 len;
622: char *s,*d;
623:
624: s = (char *)src;
625: d = (char *)dst;
626: len = *src;
627:
628: *d++ = *s++;
629: while (len-- != 0)
630: *d++ = *s++;
631:
632: return dst;
633: }
634:
635:
636: /*-------------------------------------------------------------------------------
637:
638: Routine: CStrNCopy - Copy at most n characters.
639:
640: Function: Copies upto 'max' characters from 'src' to 'dst' char strings.
641: If 'src' string is shorter than 'max', the 'dst string will be
642: padded with null characters. If 'src' string is longer than 'max'
643: the 'dst' string will NOT be null terminated.
644:
645: See ANSI X3.159-1989 p.106 - "strncpy"
646:
647:
648: Input: src - pointer to the source string of char's to copy.
649: max - maximum number of characters to copy.
650:
651:
652: Output: dst - pointer to the destination string of char's.
653:
654: Result: dst - a pointer to the destination string is returned.
655: -------------------------------------------------------------------------------*/
656:
657: char *CStrNCopy (char *dst, const char *src, UInt32 max)
658: {
659: char *pos = dst;
660:
661: max++; // bump up max so we can predecrement in tests
662: do { // copy upto max chars to dst
663: if (--max == 0) return dst; // exit if we've copied max chars
664: } while ( (*pos++ = *src++) != 0); // copy char & test
665:
666: while ( --max ) *pos++ = 0; // pad remainder of string with nulls
667: // unless we have already reached max.
668: return dst;
669: }
670:
671:
672:
673: /*-------------------------------------------------------------------------------
674:
675: Routine: PStrNCopy - Copy string of chars from src to dst.
676:
677: Function: Copies max characters from 'src' to 'dst' char strings.
678:
679: Input: src - pointer to the source string of char's to copy.
680:
681: Output: dst - pointer to the destination string of char's.
682:
683: Result: dst - a pointer to the destination string is returned.
684: -------------------------------------------------------------------------------*/
685:
686: StringPtr PStrNCopy (StringPtr dst, ConstStr255Param src, UInt32 max)
687: {
688: UInt8 len;
689: char *s,*d;
690: char count = 0;
691:
692: s = (char *)src;
693: d = (char *)dst;
694: len = *s;
695:
696: do {
697: if ( (max-- == 0) || (len-- == 0))
698: break;
699:
700: *++d = *++s;
701: count += 1;
702:
703: } while ( 1 );
704:
705: if ( count )
706: *dst = count;
707:
708: return dst;
709: }
710:
711:
712: /*-------------------------------------------------------------------------------
713:
714: Routine: CStrCat - Append 'src' char string onto 'dst'.
715:
716: Function: Appends characters from 'src' to 'dst' char strings.
717: The initial character of 'src' overwrites the null character at
718: the end of 'dst'. A terminating null character is ALWAYS appended.
719:
720:
721: Input: src - pointer to the source string of char's to append.
722:
723: Output: dst - pointer to the destination string of char's.
724:
725:
726: Result: dst - a pointer to the destination string is returned.
727: -------------------------------------------------------------------------------*/
728:
729: char *CStrCat (char *dst, const char *src)
730: {
731: char *pos = dst;
732:
733: while ( *pos++ ) // find the end of dst string
734: ;
735:
736: --pos; // backup to point to null word
737:
738: while ( (*pos++ = *src++) != 0) // copy src to dst
739: ;
740:
741: return dst;
742: }
743:
744:
745:
746:
747: /*-------------------------------------------------------------------------------
748:
749: Routine: PStrCat - Append 'src' char string onto 'dst'.
750:
751: Function: Appends characters from 'src' to 'dst' char strings.
752:
753: Input: src - pointer to the source string of char's to append.
754:
755: Output: dst - pointer to the destination string of char's.
756:
757:
758: Result: dst - a pointer to the destination string is returned.
759: -------------------------------------------------------------------------------*/
760:
761: StringPtr PStrCat (StringPtr dst, ConstStr255Param src)
762: {
763: UInt8 *pos = (UInt8 *)dst;
764: UInt8 *d = (UInt8 *)dst;
765: UInt8 *s = (UInt8 *)src;
766: UInt8 len = *s++;
767: UInt8 dlen = *d;
768:
769:
770: if (((UInt32)len + (UInt32)dlen) > (UInt32)255)
771: {
772: len = 255 - dlen;
773: }
774: pos += (*pos) + 1; // pos at end of string.
775:
776: while ( len-- != 0 )
777: {
778: *pos++ = *s++; // car src to dst
779: (*d) += 1; // dump new string length
780: }
781:
782: return dst;
783: }
784:
785:
786:
787: /*-------------------------------------------------------------------------------
788:
789: Routine: CStrNCat - Append at most n characters.
790:
791: Function: Appends upto 'max' characters from 'src' to 'dst' char strings.
792: The initial character of 'src' overwrites the null character at
793: the end of 'dst'. A terminating null character is ALWAYS appended.
794: Thus, the maximum length of 'dst' could be CStrLen(dst)+max+1.
795:
796: See ANSI X3.159-1989 p.164 - "strncat"
797:
798:
799: Input: src - pointer to the source string of char's to append.
800: max - maximum number of characters to append.
801:
802:
803: Output: dst - pointer to the destination string of char's.
804:
805:
806: Result: dst - a pointer to the destination string is returned.
807: -------------------------------------------------------------------------------*/
808:
809: char *CStrNCat (char *dst, const char *src, UInt32 max)
810: {
811: char *pos = dst;
812:
813: while ( *pos++ ) // find the end of dst string
814: ;
815:
816: --pos; // backup to point to null char
817: ++max; // bump up max so we can predecrement test
818: while ( --max && ( (*pos++ = *src++) != 0)) // append upto max chars to dst
819: ;
820:
821: if (max == 0) // if we reached max chars
822: *pos = 0; // append null character
823:
824: return dst;
825: }
826:
827:
828:
829: /*-------------------------------------------------------------------------------
830:
831: Routine: PStrNCat - Append 'src' char string onto 'dst'.
832:
833: Function: Appends characters from 'src' to 'dst' char strings.
834:
835: Input: src - pointer to the source string of char's to append.
836:
837: Output: dst - pointer to the destination string of char's.
838:
839:
840: Result: dst - a pointer to the destination string is returned.
841: -------------------------------------------------------------------------------*/
842:
843: StringPtr PStrNCat (StringPtr dst, ConstStr255Param src, UInt32 max)
844: {
845: UInt8 *pos = (UInt8 *)dst;
846: UInt8 *d = (UInt8 *)dst;
847: UInt8 *s = (UInt8 *)src;
848: UInt8 len = *s++;
849:
850:
851: len = (((UInt32)*src + (UInt32)*dst) < (UInt32)255) ? (UInt32)*src : (UInt32)255 - (UInt32)*dst;
852:
853: pos += (*pos) + 1; // pos at end of string.
854:
855: while ( (max-- != 0) && (len-- != 0) )
856: {
857: *pos++ = *s++; // car src to dst
858: (*d) += 1; // dump new string length
859: }
860:
861: return dst;
862: }
863:
864:
865: /*-------------------------------------------------------------------------------
866:
867: Routine: PStrToCStr - convert Pascal string 'src' to char string 'dst'.
868:
869: Function: Converts 1 byte Pascal string chars to 2 byte char string by prefixing
870: the ASCII byte with 0x00. The char string is terminated with a 2 byte
871: null character, 0x0000.
872:
873:
874: Input: src - pointer to the Pascal source string.
875:
876: Output: dst - pointer to the destination string of char's.
877: -------------------------------------------------------------------------------*/
878:
879: void PStrToCStr (char *dst, ConstStr255Param src)
880: {
881: unsigned char len;
882:
883: len = 1 + *src++; // add 1 so we can predecrement
884: while (--len) // for each char in src...
885: {
886: *dst++ = (char) *src++; // cast & copy chars
887: }
888:
889: *dst = 0; // append null char
890: }
891:
892:
893:
894: /*-------------------------------------------------------------------------------
895:
896: Routine: CStrToPStr - convert char string 'src' to Pascal string 'dst'.
897:
898: Function: Converts 2 byte char string chars to 1 byte Pascal string by lopping
899: off the high byte. This is NOT considered sound foreign policy, and we
900: will have to accomodate our international brethren lest they be displeased
901: with us. But, it is useful for development and debugging.
902:
903:
904: Input: src - pointer to the char source string.
905:
906: Output: dst - pointer to the Pascal destination string.
907: -------------------------------------------------------------------------------*/
908:
909: void CStrToPStr (Str255 dst, const char *src)
910: {
911: UInt32 len = 0;
912: const char *s2 = src;
913:
914: while (*src++) // how long is it?
915: ++len;
916:
917: if (len > 255) len = 255; // truncate to 255 chars
918:
919: *dst++ = (unsigned char) len++; // stuff length byte &
920: // increment so we can predecrement
921: while (--len)
922: *dst++ = *s2++; // copy len chars
923: }
924:
925:
926:
927: /////////////////////////////// Compare Routines ////////////////////////////////
928:
929:
930: /*-------------------------------------------------------------------------------
931:
932: Routine: CStrCmp - Compare two char strings.
933:
934: Function: Compares the char strings s1 and s2 by comparing the values of
935: corresponding characters in each string. It does NOT take into
936: consideration case, diacriticals, or other localization requirements.
937:
938:
939: Input: s1 - pointer to char string.
940: s2 - pointer to char string.
941:
942:
943: Result: -1 - s1 < s2
944: 0 - s1 = s2
945: 1 - s1 > s2
946: -------------------------------------------------------------------------------*/
947:
948: short CStrCmp (const char *s1, const char *s2)
949: {
950: char chr;
951:
952: while ( (chr = *s1++) != 0)
953: {
954: if ( *s2++ != chr )
955: {
956: if ( chr < *--s2 )
957: return -1;
958: return 1;
959: }
960: }
961: // here chr==0 and s2 has not advanced
962: if(*s2 == 0)
963: return 0;
964: return -1;
965: }
966:
967:
968:
969: /*-------------------------------------------------------------------------------
970:
971: Routine: PStrCmp - Compare two char strings.
972:
973: Function: Compares the char strings s1 and s2 by comparing the values of
974: corresponding characters in each string. It does NOT take into
975: consideration case, diacriticals, or other localization requirements.
976:
977:
978: Input: s1 - pointer to Pascal string.
979: s2 - pointer to Pascal string.
980:
981:
982: Result: -1 - s1 < s2
983: 0 - s1 = s2
984: 1 - s1 > s2
985: -------------------------------------------------------------------------------*/
986:
987: short PStrCmp (ConstStr255Param str1, ConstStr255Param str2)
988: {
989: UInt8 s1len,s2len;
990: char chr, *s1, *s2;
991:
992: s1 = (char *)str1;
993: s2 = (char *)str2;
994: s1len = *s1++;
995: s2len = *s2++;
996:
997: while (s1len && s2len)
998: {
999: s1len--; s2len--;
1000: chr = *s1++;
1001: if ( *s2++ != chr )
1002: {
1003: if ( chr < *--s2 )
1004: return -1;
1005: return 1;
1006: }
1007: }
1008:
1009: if((s2len == 0) && (s1len == 0))
1010: return 0;
1011:
1012: if(s1len)
1013: return 1;
1014: return -1;
1015: }
1016:
1017:
1018:
1019: /*-------------------------------------------------------------------------------
1020:
1021: Routine: CStrNCmp - Compare the first N characters of two char strings.
1022:
1023: Function: Compares the first N char strings s1 and s2 by comparing the values
1024: of corresponding characters in each string. It does NOT take into
1025: consideration case, diacriticals, or other localization requirements.
1026:
1027:
1028: Input: s1 - pointer to char string.
1029: s2 - pointer to char string.
1030: max - the number of characters to compare.
1031:
1032:
1033: Result: -1 - s1 < s2
1034: 0 - s1 = s2
1035: 1 - s1 > s3
1036: -------------------------------------------------------------------------------*/
1037:
1038: short CStrNCmp (const char *s1, const char *s2, UInt32 max)
1039: {
1040: register char c1, c2; /* s1[] may be shorter s2[] or
1041: their length may be equal */
1042:
1043: while (max--)
1044: {
1045: c1 = *s1++;
1046: c2 = *s2++;
1047:
1048: if ( c1 != c2 )
1049: {
1050: if ( c1 < c2 ) return -1;
1051: else return 1;
1052: }
1053:
1054: if(c1 == 0) return 0;
1055: }
1056:
1057: return 0;
1058: }
1059:
1060:
1061:
1062: /*-------------------------------------------------------------------------------
1063:
1064: Routine: PStrNCmp - Compare two char strings.
1065:
1066: Function: Compare the first N characters of two char strings.
1067:
1068:
1069: Input: s1 - pointer to Pascal string.
1070: s2 - pointer to Pascal string.
1071: max - N chars to compare
1072:
1073:
1074: Result: -1 - s1 < s2
1075: 0 - s1 = s2
1076: 1 - s1 > s2
1077: -------------------------------------------------------------------------------*/
1078:
1079: short PStrNCmp (ConstStr255Param str1, ConstStr255Param str2, UInt32 max)
1080: {
1081: char c1, c2;
1082: UInt8 l1, l2;
1083: char *s1,*s2;
1084:
1085: l1 = str1[0]; s1 = (char *)str1; s1++;
1086: l2 = str2[0]; s2 = (char *)str2; s2++;
1087:
1088: if ((l1 == 0) && (l2 == 0))
1089: return 0;
1090:
1091: while (max && l1 && l2)
1092: {
1093: max--; l1--; l2--;
1094: c1 = *s1++;
1095: c2 = *s2++;
1096:
1097: if ( c1 != c2 )
1098: {
1099: if ( c1 < c2 ) return -1;
1100: else return 1;
1101: }
1102: }
1103:
1104: if ((max == 0) || ((l1 == 0) && (l2 == 0)))
1105: return 0;
1106:
1107: if (l1)
1108: return 1;
1109: return -1;
1110: }
1111:
1112:
1113: /*-------------------------------------------------------------------------------
1114:
1115: Routine: CStrLen - returns length of char string in characters.
1116:
1117: Function: Returns the length of char string 'src' in characters. This does
1118: NOT include the terminating null character.
1119:
1120:
1121: Input: src - pointer to a char string.
1122:
1123: Result: number of characters in char string 'src'
1124:
1125: -------------------------------------------------------------------------------*/
1126:
1127: UInt32 CStrLen (const char *src)
1128: {
1129: UInt32 len = 0;
1130:
1131: while (*src++)
1132: ++len;
1133:
1134: return len;
1135: }
1136:
1137: /*-------------------------------------------------------------------------------
1138:
1139: Routine: PStrLen - returns length of Pascal string in characters.
1140:
1141: Function: Returns the length of Pascal string 'src' in characters.
1142:
1143: Input: src - pointer to a Pascal string.
1144:
1145: Result: number of characters in Pascal string 'src'
1146:
1147: -------------------------------------------------------------------------------*/
1148:
1149: UInt32 PStrLen (ConstStr255Param src)
1150: {
1151: UInt8 strlen;
1152: char *s = (char *)src;
1153:
1154: strlen = *s;
1155:
1156: return (UInt32)strlen;
1157: }
1158:
1159:
1160: /////////////////////////////////////////////////////////////////////////////////
1161: //
1162: // Software Interrupts
1163: //
1164: //
1165:
1166: OSErr InitSwis (void)
1167: {
1168: long i;
1169: Swi_Information *swi;
1170:
1171: PBQueueCreate (&CreatedSwis);
1172:
1173: PBQueueCreate (&AvailableSwis);
1174:
1175: AllSwis = PoolAllocateResident( sizeof(Swi_Information) * N_SWIS, true );
1176: if ( !AllSwis )
1177: return memFullErr;
1178:
1179: swi = AllSwis;
1180: for (i=0;i<N_SWIS;i++)
1181: {
1182: // swi->Name = 'SWI!';
1183: PBEnqueue ( &swi->Link, AvailableSwis);
1184: swi++;
1185: }
1186:
1187: return noErr;
1188: }
1189:
1190: /*-------------------------------------------------------------------------------
1191:
1192: Routine: CurrentTaskID - Returns ID of the Current Task. (@NON-Int Lvl)
1193:
1194: -------------------------------------------------------------------------------*/
1195:
1196: TaskID CurrentTaskID (void)
1197: {
1198: if (CurrentExecutionLevel() != kTaskLevel)
1199: {
1200: // SysDebugStr ((StringPtr)"\pCurrentTaskID not called at Task Level!");
1201: return (TaskID)-1;
1202: }
1203:
1204: return (TaskID)0;
1205: }
1206:
1207: /*-------------------------------------------------------------------------------
1208:
1209: Routine: DelayFor - Block Current Task for a Duration. (@NON-Int Lvl)
1210:
1211: -------------------------------------------------------------------------------*/
1212: /*naga
1213: OSStatus DelayFor ( Duration expirationTime )
1214: {
1215: AbsoluteTime abt;
1216: Nanoseconds nano;
1217: SInt64 divisor;
1218: SInt64 remainder;
1219: SInt64 numTicks;
1220: unsigned long finalTicks;
1221:
1222: if (CurrentExecutionLevel() != kTaskLevel)
1223: {
1224: // SysDebugStr ((StringPtr)"\pDelayFor not called at Task Level!");
1225: return -1;
1226: }
1227:
1228: abt = DurationToAbsolute ( expirationTime );
1229: nano = AbsoluteToNanoseconds ( abt );
1230:
1231: divisor.hi = 0;
1232: divisor.lo = 16666666;
1233:
1234: numTicks = S64Divide( *(SInt64*)(&nano), divisor, &remainder );
1235:
1236: Delay ( numTicks.lo, &finalTicks );
1237:
1238: return noErr;
1239: }
1240: naga */
1241: #if 0 //naga
1242: /*-------------------------------------------------------------------------------
1243:
1244: Routine: DelayForHardware - Delay for an AbsoluteTime. (Int Lvl)
1245:
1246: -------------------------------------------------------------------------------*/
1247:
1248: OSStatus DelayForHardware ( AbsoluteTime absoluteTime )
1249: {
1250: // Obtain the NanoKernel's private pointer to the ProcessorInfo structure.
1251: // This pointer is contained in the location defined by the private enum
1252: // 'ProcessorInfoPtr'
1253: NKProcessorInfo *processorInfo = *((NKProcessorInfo **) nkProcessorInfoPtr);
1254:
1255: if (gDelayForHdwrProc == nil)
1256: {
1257:
1258: // First Time Initialization
1259:
1260: if ((processorInfo->ProcessorVersionReg >> 16) == 0x0001)
1261: {
1262: // PowerPC 601 Chip (Use RTC, not TimeBase)
1263:
1264: gDelayForHdwrProc = DelayForHardware601;
1265: }
1266: else
1267: {
1268: // Non-PowerPC 601 (Use TimeBase, not RTC)
1269:
1270: gDelayForHdwrProc = DelayForHardwarePPC;
1271: }
1272: }
1273:
1274: return gDelayForHdwrProc(absoluteTime);
1275: }
1276: #endif
1277: /*-------------------------------------------------------------------------------
1278:
1279: Routine: CreateSoftwareInterrupt - Makes a SWI. (@any exec-Lvl)
1280:
1281: -------------------------------------------------------------------------------*/
1282:
1283: OSStatus CreateSoftwareInterrupt ( SoftwareInterruptHandler theHandler,
1284: TaskID theTask,
1285: void * theParameter,
1286: Boolean persistent,
1287: SoftwareInterruptID * theSoftwareInterrupt)
1288: {
1289: Swi_Info aSwi;
1290:
1291: if ( PBDequeueFirst (AvailableSwis, (QElemPtr *)&aSwi) != noErr )
1292: return paramErr;
1293:
1294: aSwi -> Handler = theHandler;
1295: aSwi -> The_Id = (SoftwareInterruptID)aSwi;
1296: aSwi -> The_Task = theTask;
1297: aSwi -> Temporary = !persistent;
1298: aSwi -> Sent = false;
1299: aSwi -> P1 = (void *)theParameter;
1300:
1301: if (theSoftwareInterrupt != nil)
1302: *theSoftwareInterrupt = (SoftwareInterruptID)aSwi;
1303:
1304: PBEnqueue ( &aSwi->Link, CreatedSwis);
1305:
1306: return noErr;
1307: }
1308:
1309:
1310: /*-------------------------------------------------------------------------------
1311:
1312: Routine: SendSoftwareInterrupt - Runs a SWI. (@any exec-Lvl)
1313:
1314: -------------------------------------------------------------------------------*/
1315:
1316: OSStatus SendSoftwareInterrupt ( SoftwareInterruptID theSoftwareInterrupt,
1317: void * theParameter)
1318: {
1319: Swi_Info aSwi;
1320: SoftwareInterruptHandler handler;
1321: Boolean temp;
1322: void *p1;
1323: OSErr Result = PBDequeue ( (QElemPtr)theSoftwareInterrupt, CreatedSwis);
1324:
1325: if (Result != noErr)
1326: return (OSStatus)Result;
1327:
1328: aSwi = (Swi_Info)theSoftwareInterrupt;
1329:
1330: // Store away swi info in locals.
1331: handler = aSwi -> Handler;
1332: p1 = aSwi -> P1;
1333: temp = aSwi -> Temporary;
1334:
1335: // Return temp swis now.
1336: if ( temp )
1337: PBEnqueue ( &aSwi->Link, AvailableSwis );
1338:
1339: // Call the handler
1340: (*handler) (p1, (void *)theParameter);
1341:
1342: // Return persistant swis later.
1343: if ( !temp )
1344: PBEnqueue ( &aSwi->Link, CreatedSwis );
1345:
1346: return noErr;
1347: }
1348:
1349: /*-------------------------------------------------------------------------------
1350:
1351: Routine: DeleteSoftwareInterrupt - Destroys a SWI. (@any exec-Lvl)
1352:
1353: -------------------------------------------------------------------------------*/
1354:
1355: OSStatus DeleteSoftwareInterrupt ( SoftwareInterruptID theSoftwareInterrupt )
1356: {
1357: Swi_Info aSwi;
1358: OSErr Result = PBDequeue ( (QElemPtr)theSoftwareInterrupt, CreatedSwis);
1359:
1360: if (Result != noErr)
1361: return (OSStatus)Result;
1362:
1363: aSwi = (Swi_Info)theSoftwareInterrupt;
1364:
1365: PBEnqueue ( &aSwi->Link, AvailableSwis );
1366:
1367: return noErr;
1368: }
1369:
1370:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.