mac-rom/Patches/PatchSEROM.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

5397 lines
212 KiB
Plaintext

;
; File: PatchSEROM.a
;
; Contains: patches for the first ROMs shipped in a Macintosh SE ($0276)
;
; Copyright: © 1985-1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <60> 1/19/92 DTY Look at emAppleTalkInactiveOnBoot before getting the AppleTalk
; version. If AppleTalk is inactive, donÕt set up the serial port
; for use by AppleTalk. This is part of a large conspiracy to
; convince the universe that AppleTalk really isnÕt around if it
; is inactive.
; <59> 8/30/91 DTY Define onMacPP & has3rdFloppy in this file now that theyÕre no
; longer available features in BBSStartup. onMacPP is 1 because
; this patch files applies to the SE ROM. has3rdFloppy is true
; because this file used to use {DefsPP}. If this file is ever
; used in a ROM build (which it probably wonÕt), has3rdFloppy is
; false because our new ROMs donÕt do that kind of thing any more.
; <58> 6/12/91 LN removed #include 'HardwareEqu.a'
; <57> 3/17/91 eh Serial driver status calls 9 and $8000 now return hardcoded
; driver version instead of getting it from DCE. This obviates the
; need for the linked patch to _Open to patch the version number
; in the DCE, a fix which was causing FileShare to crash.
; <56> 3/4/91 dba dty: get rid of SysVers conditionals
; <55> 2/21/91 eh (djw) Fixed bug in serial driver that was preventing use of one
; port when Nike was printing on the other.
; <54> 1/30/91 dnf csd/dba, #dnf003: For 7.0, remove the patch that ensured that
; BTCBs for the catalog and extents files were deallocated on
; _Eject and _Offline. We no longer close the b*tree control
; files on _Eject and _Offline, so we no longer need to
; deallocate their BTCBs.
; <53> 1/19/91 mbs (jg) Include new ATalkPrivateEQU.a to get AGBHandle equates
; since they were removed from ATalkEQU.a
; <52> 1/19/91 eh (djw) Patch portA async serial driver headers to insert
; signature long word for use in serial driver linked patch.
; Insert signature before already patched port B driver headers.
; Change port arbitration code to call new 'atkv' Gestalt call
; instead of old 'atlk' call.
; <51> 1/14/91 eh (djw) Added external clocking support for Nike Printer to the
; Async Serial Driver.
; <50> 12/15/90 djw (jwk) Add SCSI Mgr support for Quantum 7.9 ROM problem by adding
; a separate TIB interpreter and replacing blind write
; <49> 12/14/90 dnf (jsm) Turn all patches on the ExtFSHook off for 7.0. They are
; now linked patches in LaterFileMgrPatches.a
; <48> 12/13/90 BBM (stb) move the patch to compactmem into memorymgrpatches.a.
; <47> 11/26/90 JSM <bbm> Delete come-from patch on _StackSpace inside RgnOp since
; it never worked (see QuickDrawPatches.a for details), move
; come-from patches on _DisposeHandle inside CloseDialog and
; _ValidRect inside SetIText to DialogMgrPatches.a.
; <46> 11/20/90 JSM <dba> Move come-from patch on _GetResource inside GetNextEvent
; to disable FKEYs from the keypad to ToolboxEventMgrPatches.a,
; which means the entire _GetResource patch here is unneeded for
; 7.0.
; <45> 11/14/90 JSM <bbm> Move come-from patch on _TEAutoView to fix dialog manager
; bug to DialogManagerPatches.a.
; <44> 11/9/90 dba & gbm; Move LoadResource patch that checks for errors while
; loading WDEFs and CDEFs to WindowMgrPatches.a and
; ControlMgrPatches.a Ñ one more step towards the obsolescence of
; this file
; <43> 9/25/90 KIP Change Sound Mgr. to a linked patch.
; <42> 9/22/90 dba get rid of Time Mgr. patching here since we now use the real
; TimeMgr.a to make a linked patch; get rid of obsolete ADB
; patches
; <41> 9/21/90 KON Make stdBits patch a linked patch and moved it to
; AllB&WPatches.a
; <40> 8/18/90 dba get rid of ptchInst 7 and 8 (Sony Format and Eject patches) as
; they are now linked patches
; <39> 8/14/90 DTY Removed PtchInst 0 since TextEdit is now a linked patch.
; <38> 8/8/90 SAM Changing DispatchHelper & ProcHelper into an old style ptch.
; ¥¥¥--> Temporary <--¥¥¥ Remove when the Sound ptch get converted
; into an Lptch.
; <37> 8/7/90 DTY ADBMgrPatch (ptch 34) is a linked patch now.
; <36> 7/30/90 dnf Remove installation of ptch 18 (File Manager) and ptch 6 (Btree
; Manager), now linked patches
; <35> 7/23/90 dba get rid of ptch 1 since Menu Mgr. is now a linked patch
; <34> 7/23/90 dba get rid of ptch 25 for 7.0; it is covered by DialogMgrPatches;
; get rid of extraneous pre-6.0.6 SysVers conditionals; removed
; ptchInst 16 since PrGlue is a linked patch
; <33> 7/20/90 DTY Remove ptchInst 10 & 11 since Bass is a linked patch now.
; <32> 7/20/90 CCH NEEDED FOR SIXPACK: Removed HwPriv patch since it is now a
; linked patch.
; <31> 7/20/90 GMR Install ptch 7 on SuperDrive ROMS as well now.
; <30> 7/16/90 gbm Kill a few warnings
; <29> 7/16/90 DDG NEEDED FOR SIXPACK: I disabled the patch I made to fix the
; button CDEF, since it causes much more problems than it fixes.
; At some point (when I have more time) I may come back and fix
; this patch for real.
; <28> 7/2/90 DTY Removed ptchInst 21 since Resource Manager extensions are now a
; linked patch.
; <27> 6/29/90 DDG NEEDED FOR SIXPACK: Added patches to SectRgn and DrawText in
; order to fix a bug in the button CDEF.
; <26> 6/26/90 DTY Removed ptchInst 2 since Notification Manager is now a linked
; patch.
; <25> 6/25/90 DTY Removed ptchInst 9 since ScrollSpeedFix now in a linked patch.
; <24> 6/19/90 VL Get rid of ptchinst 29 since MiscPatches is a linked patch.
; <23> 6/12/90 JSM Remove PtchInst 33 since PPC Toolbox is a linked patch now.
; <22> 6/11/90 EMT Moved alternate trap dispatcher loading to boot blocks.
; <21> 6/7/90 EMT Remove PtchInst 17 since Layer Manager is a linked patch now.
; <20> 6/7/90 VL Help Mgr is now a linked patch. Get rid of ptch 28.
; <19> 5/29/90 DDG NEEDED FOR SIXPACK: Changed all the sixpack conditionals from
; six-point-oh-seven to six-point-oh-six.
; <18> 5/10/90 JSM AliasMgr now a linked patch, don't install it here anymore.
; <17> 5/2/90 BBM add makesysfree for 6.0 systems
; <16> 4/16/90 SMB Changed 'ptch' 27 conditionals to include it for 6.0.6 builds.
; <15> 4/16/90 csd moved ptch 29 (misc including Shutdown Manager) before ptch 33
; (PPC) because the PPC loader calls ShutdownInstall.
; <14> 4/16/90 DDG Rolled over some bug fixes from the system 6 split off sources
; back into the main ones: we now install patch 25 (generic
; patches for all systems) and we added a hwPriv patch. Helpers:
; BBM, djw
; <13> 4/11/90 dba get rid of patch to InitApplZone for 7.0; move PPC after B-Tree
; Manager
; <12> 4/4/90 KON get rid of ptch 44 and ptch 35 since they are now linked ptches.
; <11> 3/29/90 KON Added ptch 44, a QD patch for all B&W machines.
; <10> 3/23/90 NC Added ptch 43 for System 6.0.6 on up. This is for Sound.
; <9> 3/20/90 PWD Changed install of ATP SendRequest patch to check to see if
; AGBHandle is already allocated.
; <8> 3/7/90 dba change MyDisposHandle to use BackToTrap
; <7> 2/5/90 DDG Fix SysBeep by including it in the sound manager patch instead
; of the individual patches for each ROM. (Neil [NC] actually did
; the fix)
; <6> 2/4/90 dba get rid of SysBeepPatch because it is in the Sound Mgr. patch
; <5> 1/31/90 SMB NEEDED FOR Scripts604 and 6.0.5 - Fixed Dialog Mgr bug that
; didn't get rolled into rom. Have to do a come-from patch in
; TEAutoView to fix a rect for R-to-L text.
; <4> 1/22/90 PKE Used new InstallGestaltEarly symbol to control whether Gestalt's
; ptch 5 installation is done earlier (needed for TextEdit 3.0),
; and made it happen for SysVers>=$605 instead of SysVers>=$700.
; (This is already in the System6Proj sources).
; <3> 1/12/90 CCH Added include of ÒHardwarePrivateEqu.aÓ.
; <2> 1/4/90 dba conditionalized out WaitNextEvent for 7.0 since we always have
; MultiFinder; install BadTrap patch for DebugStr as well as
; Debugger for 7.0, since we have a large trap table; get rid of
; Launch patch for Radius for 7.0 because Ed Tecot sez, and
; because it just makes some Radius features go away, it doesnÕt
; crash (we told Radius this would happen); got rid of pre-HMenus
; Menu Mgr. patches and got rid of the HMenus conditional; got rid
; of the patch and setup that was used to do the override of the
; MBDF for switch-launching since 7.0 does not switch launch
; (MultiFinder-only); renamed some symbols and got rid of some
; extraneous equates to avoid warnings
; <1> 12/17/89 CCH Adding for the first time into BBS.
; <6.0> 12/11/89 GMR Added ptchInst 8; Sony Format patch is now in it's own patch
; file (FormatPatch.a).
; <5.9> 11/29/89 GGD NEEDED FOR 6.0.5 Enabled the Extended Time Manager (which
; matches the code that is in the IIci/Portable ROMs) Enabled the
; New ADB Manager (which matches the code that is in the IIci ROM)
; Initialized the new LowMem TimeViaDB which was introduced with
; the IIci ROM
; <5.8> 11/21/89 EMT NEEDED FOR 6.0.5: Added humane scrolling.
; <5.7> 11/10/89 rwh NICE FOR 6.0.5: for ptch38, remove check for hwPriv already
; <5.6> 10/25/89 rwh NICE FOR 6.0.5: add ptch38, backpatch hwPriv for accelerated
; SE's.
; <5.5> 10/16/89 csd Moved the code that installs the expanded trap dispatcher to the
; start of the install section, above all other patches.
; <5.4> 10/15/89 BAL Added support for 32-Bit QuickDraw pictures via ptch 35
; <5.3> 10/14/89 GMR Re-added ptch34 - ADB manager patch, for system 7.0
; <5.2> 10/10/89 GMR Backed out ptch 34, until it can be cleaned up
; <5.1> 10/6/89 JSM Removed SnarfMan 'ptch', now PACK 13.
; <5.0> 10/3/89 GMR Added ptch 34, Gary D's new ADB manager, for 7.0.
; <4.9> 9/26/89 CVC Added the PPC Toolbox as a 'ptch'.
; <4.8> 9/4/89 PKE Install Script Manager 7.0 extensions, ptch 27.
; <4.7> 8/28/89 SES Removed references to nFiles.
; <4.6> 8/22/89 PKE NEEDED FOR 6.0.4 (SCRIPTS BUILD) & 7.0: Conditionalize 4.5 for
; Scripts604 OR (SysVers >= $700)
; <4.5> 8/19/89 PKE NEEDED FOR 6.0.4 (SCRIPTS BUILD) & 7.0: Moved PtchInst 5
; (Gestalt) ahead of (most) other PtchInsts so they can use
; Gestalt.
; <4.4> 8/9/89 GMR Added ptch 29 - BigBang only patches for all ROMs
; <4.3> 8/1/89 BG Modified the conditional in <4.1> to be (SysVers >= $700) to
; make sure that this patch never appears in a 6.0.x build.
; <4.2> 7/25/89 GMR Needed for 6.0.4: Added Sony Eject patch (ptch 7)
; <4.1> 7/7/89 BG Added Gary D.'s optimized A-Trap dispatcher (which adds an
; extended Toolbox trap table) to the Mac SE.
; <4.0> 6/30/89 BBM Added resource mgr extensions ('ptch' 21)
; <3.9> 6/29/89 RLC Added HelpMgr PtchInst #28
; <3.8> 6/21/89 NJC Added a ptchinst 3 to if it wasn't already there and added in a
; commented-out ptchinst 23 for the sound dispatcher,DJ, and S.M.
; enhancements.
; <3.7> 6/13/89 dnf Moved btree ptch install after hfs70 ptch install.
; <¥3.6> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw private
; file (colorequ.a), got rid of QuickDraw nFiles dependencies and
; fixed up necessary filesÉ
; <3.5> 5/31/89 CEL Only defined Spline_Font variable if it is undefined - makes it
; easier to build test 6.0.4 systems
; <3.4> 5/31/89 prp Added Alias Manager Support
; <3.3> 5/30/89 dnf Added HFS 7.0 Enhancements (ptch 18)
; <3.2> 5/26/89 CCH Conditionalized out install of 6.0.4 PrGlue.
; <3.1> 5/25/89 CCH Re-added PrGlue patch taken out in v2.4 for 6.0.4.
; <3.0> 5/23/89 EVA SysVers conditional is $700 for deferred task patch
; <2.9> 5/23/89 jaz Change version conditionals to check for $700 instead of $604
; <2.8> 5/19/89 jaz Add code to patch in Gary D's new Extended Time Manager
; <2.7> 5/18/89 ggd (Really EH) Add Deferred Task Manager and patched Level 1 thru 3
; interrupt handlers.
; <2.6> 5/16/89 EMT Moved include of ToolTrapFix so that it would be executed at
; installation time.
; <2.5> 5/13/89 EMT Added Window Manager extensions (Layers).
; <2.4> 5/8/89 NMB Replaced PrGlue with Ginsu's PrGlue.
; <2.3> 5/3/89 CEL Rolling in Bass for the first time into EASEÉ
; <2.2> 4/18/89 JSM Install SnarfMan 'ptch'.
; <2.1> 4/17/89 CCH Rolled out Altair changes.
; <2.0> 3/22/89 CCH Now looks for DiskCachePriv.a in {AIncludes}.
; <1.9> 3/21/89 KST Added install code to bring in Btree Manager.
; <1.8> 3/17/89 CCH Fixed install of Cache Control Trap so that it installs on
; 6.0.4.
; <1.7> 2/22/89 CCH Added install code to bring in Gestalt patch.
; <1.6> 2/21/89 JB (DNF, actually) These files seems to work, so I'm checking them
; back in.
; <1.5> 2/20/89 JB Cleaned up revision history comments.
; <1.4> 2/20/89 JB Moved MapFBlock and "not a Mac disk" ExtFSHook patches from
; BeforePatches.a
; <¥1.3> 2/20/89 JB Moved cache control trap from BeforePatches.a
; <1.2> 1/31/89 CCH Merged changes from 6.0.3.
; <1.1> 1/16/89 CCH Merged 6.0.3 final sources into 7.0.
; <1.0> 11/16/88 CCH Added to EASE.
; PMAB581> 10/16/88 GGD Installed latest version of TimeMgr, which also includes work
; around for bug with Rockwell VIAs (6.0.3 and Altair) Replaces
; PMAB564
; PMAB574> 9/25/88 jwk Rolled enhancements to old SCSI Mgr to support new SCSI Mgr
; trap.
; <PMA572> 9/22/88 jwk Added Deferred Task Mgr to the Plus and SE.
; PMAB564> 8/18/88 ggd Patched in the New Improved Time Manager for all CPUs,
; Completely replaces old Time Manager, and replaces patches on
; MacPlus and MacSE.
; <PA511> 6/24/88 JB Added patch to fix UpdAltMDB to use correct disk address on
; 1440k disks
; <S497> 6/7/88 med Changed Script Manager to ptch resource
; <PA489> 5/4/88 EMT Addition to PA419 - Remove Radius SetTrapAddress patch.
; <s481> 4/27/88 bbm There was a small window after the vremove where a timer
; interrupt could happen. Since the sound driver services the
; timer in the vbl task, the code to reinstall the vbl task would
; never happen.
; PMAB466> 4/13/88 JWK Fixed SCSIGet to perform cleaner arbitration.
; PMAB457> 4/7/88 RWW Fixed CloseDialog to properly dispose TERecord
; PMAB449> 3/30/88 rwh replace SysEnvirons code w/INCLUDE SysEnvirons.a (Version 2!)
; PMAB442> 3/25/88 EKH Fixed 'PatchInstall' fail bug. (Wasn't calling SysErr
; correctly).
; <PA419> 3/4/88 EMT Radius FPD SE disables PMA314 - patch PA176 to reassert.
; <PMA418> 3/4/88 EMT Fix bug in PMA314 which left ROMMapInsert set.
; PMAB407> 2/26/88 DAF Removed PMAB370 (UprStr). I didn't know that you could use
; UprStr to just strip diacriticals. My post processing was
; causing AppleShare to get grave accents accidentally when
; stripping names. This can still be fixed, it just requires a
; deeper fix rather than post processing.
; PMAB401> 2/23/88 djw Bug in async driver - killIO did not set reg D0 to good return
; status. Combine with patch PMAB372
; <PMA399> 2/21/88 DAF Fixed StdBits to use (corrected) PackBits (for Scanner app).
; PMAB372> 1/26/88 djw Fixed DTR bug in async serial driver - a jump to the wrong label
; PMAB370> 1/25/88 DAF UprStr had an "a" instead of a "`" in it's case table, so I
; added a post-call scan of the string to fix this.
; <PMA361> 1/18/88 AWC Add fast polygon stuff to PatchPlusROM.a, PatchSEROM.a
; PMAB354> 1/7/88 EMT Unimplemented Toolbox versions of 12 bisexual traps
; PMAB344> 12/22/87 JSP Modified to not install sony driver patches if version number of
; driver is greater than one.
; PMAB340> 12/17/87 EMT Miscellaneous fixes to NMgr + System Alarm uses NMgr.
; PMAB335> 12/15/87 EMT ptchInstall now calls SysError on failure
; PMAB329> 12/10/87 JWK Fixed PMAB295 to avoid 10 sec delay when booting with no SCSI
; devices attached.
; <PMA325> 12/8/87 jw new SysBeep, calls SndPlay like on Mac II
; PMAB318> 11/30/87 jw Added new improved sound manager.
; PMAB317> 11/28/87 EMT Added Notification Manager.
; PMAB315> 11/25/87 RWW Err, GetResource doesn't return resNotFound? Fixed ptchInstall
; <PMA314> 11/25/87 EMT Patch GetResource to get MBDF instead of ROM override on Plus,
; SE
; PMAB308> 11/24/87 RWW Added ptchInstall, which installs 'ptch' resources. This saves
; keeping duplicate copies of identical code in several patch
; files.
; <PMA311> 11/24/87 EMT Install Menu Manager using 'ptchInstall' method. Undoes PMA097.
; PMAB309> 11/24/87 RWW Massive, world-shattering change - yank TE patches and do this
; whizzy new installation. This one patch, in one fell swoop,
; replaces the following old, sometimes ugly patches: P001, P002,
; P003, P004, P013, P016, P017, P018, P024, P025, P026, PO31,
; P032, P033, P034, P035, P036, P037, P038, P039, P040, P041,
; PA064, PA065, PA066, PA070, PA085, PABM139, PABM197, PABM198,
; PA199, PA200, PABM201, PABM202, PABM203, PABM250
; PMAB305> 11/22/87 DAF Fixed RgnOp buffer calculation bug.
; PMAB301> 11/15/87 ABO Fix ATP delayed duplicate response bug
; <PMA299> 10/27/87 NMB Fixed DrText using _StdTxMeas so that QuickDraw could cope with
; fonts >128Kb.
; <PM298> 10/27/87 NMB Replaced FMSwapFont since the Font Manager couldn't cope with
; fonts >128Kb. That has been fixed.
; PMAB295> 10/20/87 SHF Modified last call to SCSILoad -- increased patched select
; timeout to 25 msec (was 5); made more robust for CD ROM.
; <PAB291> 9/26/87 DBG Changed mouse button debounce time back to 20 msec, and changed
; code so that mouse downs always get noticed. The code will now
; never discard a down/up pair, only up/down pairs.
; <PAB288> 9/24/87 CSL Reduced the mouse button delayed time from 20 msec. to 10 msec.
; PMAB284> 9/21/87 JTC Fix patch to MoveHHi to prevent dinky free blocks from being
; created. Patch involves just adding to the part of the loop
; already patched.
; <pma287> 9/18/87 bbm sound manager uses sound manager uses soundactive different than
; sound driver. Thus soundactive could be true with no sound vbl
; task installed. So now we check for an error from vremove, which
; we should have done in the first place. (This is the same patch
; as S278, which got deleted when PMAB284 was checked in.)
; PMAB270> 9/13/87 FJL Fix DrawPicture patch (in DrawPicturePatch.a) to first check for
; valid picture handle and pointer, then do GetState, lock, and
; SetState on return. At the request of Sheila, Phil and Scott.
; <PA267> 9/8/87 CRC Fixed silly bug in GetMaskTab (FMSwapFont) patch.
; <s263> 9/7/87 bbm The current sound driver uses low memory as a vbl queue element.
; A bug occurs if sound is active. The low memory queue element is
; zeroed regardless if there is a next element in the queue or
; not. Thus the machine may hang. The fix forces the sound vbl
; queue element to be last in the queue always.
; PMAB253> 8/27/87 CRC Fixed MaxSizeRsrc in FontMgr for Radius (once again)
; PABM250> 8/25/87 MBK TextEdit: Patched DisposPtr and StackSpace to fix Pixel2Char
; dispose bug
; PMAB241> 8/25/87 RDC Added patch for BadTrap handler routine to save registers before
; exiting to SysError routine - needed for new MacsBug.
; <PAB229> 7/23/87 WRL MouseDrvr MouseDrvr New, improved mouse button debouncing code
; for ADB machines.
; <PMA218> 7/22/87 JTC InitApplZone InitApplZone Patch InitApplZone to base
; ApplLimit/HiHeapMark on SP not BufPtr. This helps at start time
; when the stack world is in the middle of RAM and some hoggish
; apps want to do a MaxApplZone on the miniheap.
; PMAB226> 7/21/87 GWN Backout PMAB216.
; PMAB216> 7/21/87 GWN Patch Read, Write, Control and Status to fix Async problem.
; <PMA211> 7/20/87 SHF SCSIRead,SCSIWrite,SCSIRBlind,SCSIWBlind SCSIMgr.a SCSI Mgr:
; fixed scLoop bug in TIB interpreter.
; PMAB210> 7/20/87 DAF LoadResource CallWindow,CallControl Improved handling of CDEFs
; and WDEFs for Juggler
; <PMA207> 7/17/87 EHB PackBits PackBits Patched packBits to allow scanlines > 127
; bytes
; <PA199> 7/9/87 MBK GetFontInfo TESetStyle TextEdit: Fix to SE patch that set point
; size of 0 to 1 (should leave it)
; PABM203> 7/9/87 MBK FindLine RecalLines TextEdit: Fix to deletion bug (display would
; get messed up)
; PABM202> 7/9/87 MBK FindLine RecalLines TextEdit: Fix to recalibration bomb when
; text length = 32,767
; PABM201> 7/9/87 MBK FindLine SetLineHite TextEdit: Fix to allow fixed line heights
; to work
; <PA200> 7/9/87 MBK TextWidth Char2Pixel TextEdit: Fix to check if style record
; before accessing style handle
; PABM197> 7/9/87 MBK HLock TEStylInsert TextEdit: Fix to TEStylInsert call when
; record is deactivated
; PABM198> 7/9/87 MBK HLock,HUnlock,TEDispose,TESetSelect,TEClick,TEDispatch,TEKey
; TextEdit: Fix to allow styles to be set at null selection
; <PAB191> 7/2/87 CSL ADBReInit Kbd.a Added pre- and post- processing routine hook for
; ADBReinit.
; <PAB192> 7/2/87 EMT ADBProc KbdDrvr Use JADBProc to clean up on ADBReInit
; PABM186> 7/1/87 CRC GetResource RealFont Took out PA165 and replaced GetHandleSize
; with MaxSizeRsrc. also added part of underline fractEnable bug
; fix below.
; PABM187> 7/1/87 CRC GetMaskTable FMSwapFont two bugs: if fractEnable is false, do
; not use style widths w/o strike underline measures wrong with
; fractEnable true: pesky BEQ should have been a BMI
; <PAB185> 6/29/87 ABO Fix NBP write-to-zero on lookup bug.
; <PA182> 5/21/87 CSL DiskSelect DiskSelect Fixed the performance problem of the upper
; internal floppy drive.
; <s483> 4/27/87 bbm changed a hardwired number to HiIntMask (see s481).
; <PA176> 4/13/87 JTC Launch Launch Add diagnostic vector for last-chance patching
; before Finder launch.
; PABM139> 3/26/87 MBK FindLine TextEdit.a: RecalLines Fixed recal deletion bug.
; <PAB117> 3/19/87 CRC LoadResource FMSwapFont if fast path fails because of disk
; switch, recover with panache.
; PBAM109> 3/17/87 CRC ValidRect GetIText patched ValidRect to restore register
; clobbered by DrawItem in SetIText
; <PMA100> 3/10/87 DAF FindWindow wmgr InitWindows wmgr Patched InitWindows and
; FindWindow to use mbdf (PMA097)
; PMAB102> 3/10/87 EMT GetResource GetNextEvent Fixed all patches to not use FKEYs when
; code came from keypad.
; <PMA097> 3/10/87 FJL Back-patch hierarchical menus.
; <PA088> 3/9/87 JTC CompactMem mem mgr: MoveHHi Stop creating bogus tiny blocks.
; <PAB87> 3/6/87 CSL Patch JcrsrTask to support absolute cursor position.
; <PA085> 3/5/87 MBK HUnlock TextEdit.a:InsertRecal fixed obscure recal bug
; <PA077> 3/3/87 CRC FreeMem font manager changed to MaxBlock (better call)
; <PA077> 3/3/87 CRC FixMul font manager fix rounding bug in scaling
; <PA077> 3/3/87 CRC FixRound font manager allow font sizes greater than 127
; <PA077> 3/3/87 CRC GetResource font manager look for empty FONDs, too small fonts,
; etc.
; <PA081> 3/3/87 SHF SCSICmd SCSIMgr.a:SCSICmd fix too short a timeout waiting for
; cmd phase
; <P023> 1/13/87 JNP Print trap ($A8FD) patch. A bug was fixed after the Maui ROMs
; were frozen. Hence this patch. The bugfix was as follows: If the
; GetResource call to get a PDEF fails, don't give up. The printer
; resfile may not be in the resource search path. Save and restore
; the user resource map around the GetResource (for PDEF) call.
; Get the printer resfile refnum from the low memory print var
; ($944+$E) or open the printer resource file to get it. After
; opening the printer resource file, save the refnum in low
; memory. The code to get the printer resfile refnum is now in a
; procedure called OpenRF. Check the print error after _PrDrvrOpen
; call in PrintOpen. Added includes for PrEqu.a and PrPrivate.a
; <P015> 12/12/86 EMT GetOSEvent OSEventMgr.a:GetOSEvent OSEventAvail
; OSEventMgr.a:OSEventAvail KbdDrvr kbd.a:KbdDrvr Keyboard global
; shuffle for Excel
; <P014> 12/10/86 TJ WakeUp SonyQDUtil.a Recursion path via PrimeTime PrimeTime
; TimeMgr.a inconsistencies at some boundary conditions
; <C480> 12/1/86 Fixed FOutExtra set up for Laserwriter fonts in cache
;
IF (&TYPE('SPLINE_FONT') = 'UNDEFINED') THEN
SPLINE_FONT: EQU hasSplineFonts
ENDIF
IF (&TYPE('USE_MAKESYSFREE') = 'UNDEFINED') THEN
USE_MAKESYSFREE: EQU 1 ; need to expand the system heap for 6.0 systems
ENDIF
IF (&TYPE('Scripts604') = 'UNDEFINED') THEN
Scripts604: EQU 0
ENDIF
if (&type('onMacPP') = 'UNDEFINED') then
onMacPP: equ 1
endif
;
; has3rdFloppy was defined for {DefsPP}. Make it so for System builds.
;
if (&type('has3rdFloppy') = 'UNDEFINED') then
if forROM then
has3rdFloppy: equ 0
else
has3rdFloppy: equ 1
endif
endif
STRING ASIS
LOAD 'StandardEqu.d'
include 'ATalkEqu.a' ; <PABM150>
include 'ATalkPrivateEqu.a' ; <53>
include 'ApplDeskBus.a'
include 'AppleDeskBusPriv.a'
include 'HardwarePrivateEqu.a'
include 'PrEqu.a'
include 'PrPrivate.a'
include 'ColorEqu.a'
include 'SCSIEqu.a'
include 'SonyEqu.a'
include 'PrintCallsEqu.a'
include 'DiskCachePriv.a' ; P003 <21Feb89><2.0>
INCLUDE 'PatchMacros.a'
INCLUDE 'ScriptPriv.a' ; <16>
INCLUDE 'GestaltEqu.a'
SONYVERLOC EQU $434709 ; location for checking sony version number
ROM76Fix MAIN EXPORT
IMPORT RamSysInit
EXPORT SysBase,CutBack
; Cut back Code:
;
; SysBase is the entry point for ROM76Fix. Upon entry D1.L contains our handle.
;
; Once the patches have been installed, this code is cut back to exclude the patch
; installation code.
SysBase
BRA RamSysInit ; do the patch installation.
DC.L ('PTCH') ; resource type
DC.W $0276 ; patch ID $76 machine $02.
DC.W 0 ; current version number.
; cut back the ram-based system code to exclude this initialization code
CutBack
_SetHandleSize ; adjust our size
MOVEQ #$7F,D0 ; a soon to be large number
SWAP D0
_CompactMem ,SYS ; optional comma
RTS ; all done
;################################ PATCH CODE GOES HERE #######################################
;___________________________________________________________________________
;
; P014 TJ 09dec86 TJ WakeUp SonyQDUtil.a
; Raised int level to prevent recursion through PrimeTime.
;
; A patch to the Sony Driver's wakeup routine to prevent driver re-entry.
; Symptoms are that the file server crashes or hangs randomly when accessing
; the HD-20, every few weeks.
;
; Derived from ROM75FIX patch #52.
;
;___________________________________________________________________________
SonyWakeUp PROC EXPORT
;
;Special addresses:
;
ROMWakeup EQU $4351a0 ; ROM wakeup entry point
or.w #$0300,sr ; lock out VIA interrupts,
jmp ROMWakeup ; And enter normal wakeup routine
ENDPROC
;___________________________________________________________________________
; P015 12Dec86 EMT GetOSEvent OSEventMgr.a:GetOSEvent
; OSEventAvail OSEventMgr.a:OSEventAvail
; KbdDrvr kbd.a:KbdDrvr
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 12Dec86 #P015 (GetOSEvent) (GetOSEvent)
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 12Dec86 #P015 (OSEventAvail) (OSEventAvail)
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 12Dec86 #P015 (KbdDrvr) (KbdDrvr)
;
; This patch is to shuffle around some globals used for autokey events.
;
; Microsoft Excel expects KeyLast to be 0 if no auto key events are pending.
; When ADB was introduced, it became necessary to use the entire event message,
; not just the low word. KeyLast was thus too small to contain the repeat
; event message. KeyLast was relocated to KbdVars and given the name NewKeyLast.
; KeyLast became KbdLast and held the ADB address of the last keyboard typed on.
; This caused Excel to thrash when calculating. Thus, KeyLast has been restored
; to its original meaning; NewKeyLast becomes HiKeyLast and contains the high
; word of the repeating event message. KbdLast is relocated to KbdVars+2
; (HiKeyLast+2). All these changes have been reflected in nSysEqu.a.
;_______________________________________________________________________
GetOSEvent PROC EXPORT
EXPORT OSEventAvail,KbdDrvr
PostEvent EQU $403EE6
OsEventTail EQU $403FEA ; Address of rest of GetOSEvent
PEA OsEventTail
;_______________________________________________________________________
;
; Routine: OSEventavail
;
; Arguments: A0 (input) -- pointer to user event record (32-bit)
; D0 (input) -- set of events desired (event mask)
; D0 (output) -- 0=non-null event returned, -1=null event
; returned
; A0 (output) -- pointer to user event record
; A1 (output) -- pointer to event queue element when D0=0
; (used internally by GetNextEvent)
;
; Function: This routine polls for availability of certain types of events.
; The user-specified event record format is identical to that of
; the queue element, except for the queue header fields. If no
; events are available, the null event is returned along with
; a -1 result code in D0.
;
; EventAvail is also called by GetNextEvent.
;
; Calling sequence: MOVE.W #EventMask,D0
; LEA EventBuffer,A0
; _EventAvail
;
; Other: uses D0,D1,D2,A0,A1
;_______________________________________________________________________
NoEvtAvail EQU -1 ; (moved from SysErr.Text)
EvtOffset EQU 6 ; event record offset from start of
; event queue element
OSEventAvail LEA EventQueue,A1 ; get address of event queue
; Since PostEvent could dequeue the first element at any time, the event you
; are on may suddenly be recycled and you may end up dequeueing a different event
; or suddenly find yourself at the end of the queue when you were just at the
; beginning. By disabling interrupts during the search, this is avoided.
MOVE SR,-(SP) ; save interrupt state
ORI #HiIntMask,SR ; no event-generating interrupts <C173 24Sep86>
MOVE.L QHead(A1),D1 ; get address of 1st element
BEQ.S TstAutoEvent ; if nil, check for auto events
EventALoop MOVE.L D1,A1 ; get pointer into A-reg
MOVE EvtNum+EvtOffset(A1),D1 ; get its event number
BTST D1,D0 ; is it one we want?
BNE.S GotEventAvail ; if so, we got one!
MOVE.L QLink(A1),D1 ; follow the link to the next one
BNE.S EventALoop ; if we got one, check it out
; there wasn't an event in the queue for us, so check for auto events
TstAutoEvent AND.W SysEvtMask,D0 ; figure in system mask for pseudo-evts
BTST #AutoKeyEvt,D0 ; do we want this kind?
BEQ.S NoEventAvail ; go on if not
MOVE.W HiKeyLast, D0
SWAP D0
MOVE.W KeyLast, D0
TST.L D0 ; Key down to auto-repeat?
BEQ.S NoEventAvail ; if not, return null event
MOVE.L Ticks,D1 ; check first threshold
MOVE.L D1,D2
SUB.L KeyTime,D1
CMP KeyThresh,D1
BLT.S NoEventAvail ; br if not time yet
SUB.L KeyRepTime,D2 ; check second threshold
CMP KeyRepThresh,D2
BLT.S NoEventAvail ; br if not time yet
MOVE.L Ticks,KeyRepTime ; repeat it: first note the time
MOVE.L A0,-(SP) ; save pointer to user's buffer
MOVE #AutoKeyEvt,A0 ; get event number
JSR PostEvent ; go post it (event message already in D0)
MOVE.L A0,A1 ; get pointer to event queue element
MOVE.L (SP)+,A0 ; restore pointer to user's buffer
; and return the event
GotEventAvail MOVE (SP)+,SR ; restore interrupt state
MOVEQ #(EvtBlkSize/4),D0 ; get size of evt record in longwords
MOVEM.L A0-A1,-(SP) ; preserve regs
ADD.L #EvtOffset,A1 ; bump to record part of event element
@1 MOVE.L (A1)+,(A0)+ ; move it into user's buffer
SUBQ #1,D0
BNE.S @1 ; loop till done
MOVEM.L (SP)+,A0-A1 ; get regs back
RTS ; D0 is zero
; there wasn't any event available so return the null event in the users event
; record and a flag in D0
NoEventAvail BSR.S FillRecord ; fill in record for null events
MOVE (SP)+,SR ; restore interrupt state
CLR.W EvtNum(A0) ; return the null event
CLR.L EvtMessage(A0) ; zero message for null events
MOVEQ #NoEvtAvail,D0 ; and D0 non-zero
RTS
; FillRecord fills out the standard fields in an event record pointed to by A0
FillRecord MOVE.L Ticks,EvtTicks(A0) ; fill in the current time
MOVE.L Mouse,EvtMouse(A0) ; and the current mouse point
MOVE KeyMap+6,D1 ; get meta-key states
ROL.W #1,D1 ; rotate around
MOVE.B D1,EvtMeta(A0) ; update metakey field
MOVE.B MBState,EvtMBut(A0) ; get mouse button state
RTS
;______________________________________________________________________
;
; Routine: KbdDrvr
; Arguments: D0.B ADB Command
; A0 ADB Buffer address
; A1 ADB Completion Routine Address (= KbdServ)
; A2 ADB Data Address
; Output: None
; Function: Reads buffer and posts keyboard events as appropriate.
; Side Effects: Trashes A0, A1, D0, D1, D2, D3
;
; Modification History:
; 26 Jun 86 EMT Created
; 15 Jul 86 EMT Updated to use KCHR resource
; 21 Jul 86 EMT Complete rewrite - to use new _KeyTrans
; 3 Oct 86 EMT Added LED bells & whistles
;<A230/17Oct86> EMT D1 is no longer a parameter to this routine. Must get ADB Address from D0
;______________________________________________________________________
; Keyboard driver data
KBufCount EQU 2 ; <C201/07Oct86>
KBufLen EQU 10 ; 8 bytes + length + inuse <C201/07Oct86>
KMAPPtr EQU $00
KeyBits EQU KMAPPtr+4
KCHRPtr EQU KeyBits+(128/8)
DeadKey EQU KCHRPtr+4
KNoADBOp EQU DeadKey+4 ; <C201/07Oct86>
KNumBufs EQU KNoADBOp+1 ; <C201/07Oct86>
KFirstBuf EQU KNumBufs+1 ; <C201/07Oct86>
KbdDSize EQU KFirstBuf+(KBufCount*KBufLen) ; <C201/07Oct86>
; KMAP offsets
KMid EQU $00
KMtype EQU $01
KMvers EQU KMid+2
KMstart EQU KMvers+2
KMnumEx EQU KMstart+128
KMstEx EQU KMnumEx+2
KbdDrvr ; <C93/29Jul86>
MOVE.L A2, D3 ; See if A2 actually contains a pointer
BEQ KbdDone ; If not, can't go on.
MOVE.L A0, A1 ; Save A0 in A1 <A230/17Oct86>
LSR.W #4, D0 ; Shift ADB Address down to low nibble <A230/17Oct86>
MOVEQ #$F, D1 ; Mask for ADB Address <A230/17Oct86>
AND.L D1, D0 ; D0 now contains ADB Address <A230/17Oct86>
MOVE.L D0, D3 ; Save it in D3 <A274/27Oct86>
LEA -10(SP), SP ; Build parameter block on stack <A230/17Oct86>
MOVE.L SP, A0 ; Point to it <A230/17Oct86>
_GetADBInfo ; <A230/17Oct86>
ROR.L #8, D3 ; Rotate ADB Address to high byte <A230/17Oct86>
MOVE.W (SP)+, D3 ; Put Device Type, Orig Addr in low word<A230/17Oct86>
ADDQ.L #8, SP ; Clear off the rest of the stack <A230/17Oct86>
SWAP D3 ; D3 is now Device Type, Orig Addr, ADB Addr, Unused <A230/17Oct86>
MOVE.B 1(A1), D0 ; Get first stroke <A230/17Oct86>
MOVE.B 2(A1), -(SP) ; Save second one on stack <A230/17Oct86>
BSR.S KeyIn
MOVE.B (SP)+, D0 ; Get second stroke
;______________________________________________________________________
;
; Routine: KeyIn
; Arguments: D0.B Raw Keycode
; D3.L Device Type, Orig Addr, ADB Addr, Unused
; A2 Private data area
; Output: None
; Function Translates keycode and posts event as appropriate.
; Side Effects: Trashes A0, A1, D0, D1, D2, D3
; Called From: KbdDrvr twice, (1 BSR, 1 fall-through)
;______________________________________________________________________
KeyIn
CMP.B #$FF, D0 ; Is it not a key?
BEQ KbdDone ; Skip if so
CLR.W KeyLast ; Stop repeating <***>
CLR.W HiKeyLast ; Stop repeating <***>
MOVEQ #$7F, D1 ; Mask = 01111111 binary
AND.B D0, D1 ; Clear all but low 7 bits
MOVE.L KMAPPtr(A2), A1 ; Get KMAP table address
MOVE.B KMstart(A1, D1), D3 ; Get device independent keycode <C201/07Oct86>
BPL.S NoExcept ; Handle normally if high bit clear <C201/07Oct86>
; An exception has been indicated. Find the correct entry in the exception
; table and handle as appropriate.
BCLR #7, D3 ; Clear the high bit <C201/07Oct86>
LEA KMnumEx(A1), A0 ; Get to the beginning of the exceptions<C201/07Oct86>
MOVE.W (A0)+, D2 ; Number of entries in table <C201/07Oct86>
BEQ.S NoExcept ; Skip if none <C201/07Oct86>
SUBQ.W #1, D2 ; Turn it into a zero-based count <C201/07Oct86>
ExLoop
CMP.B (A0)+, D0 ; See if this is the one <C201/07Oct86>
BEQ FoundEx ; Skip if so <C201/07Oct86>
MOVE.B 1(A0), D1 ; Get the string length <C201/07Oct86>
LEA 2(A0, D1), A0 ; Point to the next entry <C201/07Oct86>
DBRA D2, ExLoop ; Go around again <C201/07Oct86>
NoExcept
MOVEQ #0, D2 ; Clear out D2 <C201/07Oct86>
MOVE.B D3, D2 ; Copy virtual keycode to D2 <C201/07Oct86>
LSR.W #3, D2 ; Divide by 8 for byte offset
TST.B D0 ; Up or down key?
BMI.S KeyUp ; Skip around if key up
BSET D3, KeyBits(A2, D2) ; Set it for key down
BRA.S Hammer
KeyUp
BCLR D3, KeyBits(A2, D2) ; Clear it for key up
BSET #7, D3 ; Remember key up for raw key.
Hammer
MOVEM.L KeyBits(A2), D0-D2/A0
MOVEM.L D0-D2/A0, KeyMap ; Hammer in the correct keymap
MOVE.L D3, D0 ; Bits 15-8 contain ADB address
LSR.L #8, D0 ; Put it in the low byte <C219/14Oct86>
MOVE.B D0, KbdLast ; Stuff it down
SWAP D0 ; Now get DeviceType
MOVE.B D0, KbdType ; Update KbdType to show last one used
; The next two instructions build the byte of modifier flags from the
; global key state information. This works because the modifier flags
; exist in bits $37 to $3E, which appear in the following manner:
; Byte | 6 | 7 |
; Bit |37 36 35 34 33 32 31 30|3F 3E 3D 3C 3B 3A 39 38|
; |^^ | ^^ ^^ ^^ ^^ ^^ ^^ ^^|
MOVE.W KeyBits+6(A2), D0 ; Get modifier word
ROL.W #1, D0 ; Rotate in command key
SUBQ.L #4, SP ; Make room for result
MOVE.L KCHRPtr(A2), -(SP) ; Push address of KCHR resource
MOVE.W D3, -(SP) ; Push keycode (w/o modifiers)
MOVE.B D0, (SP) ; Put modifiers where they belong
PEA DeadKey(A2) ; Push address of dead key state
_KeyTrans
MOVE.W (SP)+, D0 ; Get the high word first
BEQ.S NextWord ; Skip if null
BSR.S PostIt ; Otherwise post the event
NextWord
MOVE.W (SP)+, D0 ; Get the other word
BEQ.S KbdDone ; If null, we're done
;______________________________________________________________________
;
; Routine: PostIt
; Arguments: D0.W ASCII Code
; D3.W ADB Address in high byte and raw keycode in low byte
; Output: None
; Function Posts the keyboard event as appropriate.
; Side Effects: Trashes A0, D0, D1
; Called From: KeyIn twice, (1 BSR, 1 fall-through)
;
; Modification History:
; 25 Jun 86 EMT Created
; 22 Jul 86 EMT Changed order of event data (FHRL -> HFRL)
;<A230/17Oct86> EMT Clear the up/down bit in the event message
;______________________________________________________________________
PostIt
ROR.W #8, D0 ; Swap ASCII high and low byte (xxLH)
SWAP D0 ; Move to high word (LHxx)
MOVE.W D3, D0 ; Move in ADB address and raw keycode (LHFR)
ROL.L #8, D0 ; Rotate around (HFRL)
TST.B D3 ; Key up or down?
BMI.S PostKeyUp ; Skip if key up
MOVE.L Ticks, D1
MOVE.L D1, KeyTime ; Mark the time for auto repeat
MOVE.L D1, KeyRepTime
MOVE.W D0, KeyLast ; Save event message <***>
SWAP D0
MOVE.W D0, HiKeyLast ; Save high word too <***>
SWAP D0
MOVE #KeyDwnEvt, A0 ; Get event number
_PostEvent ; Post it
KbdDone
RTS ; And leave
PostKeyUp
MOVE #KeyUpEvt, A0 ; Get event number
BCLR #15, D0 ; Clear the up/down bit in the raw keycode <A230/17Oct86>
_PostEvent ; Post it
RTS ; And leave
; End KbdDrvr <C93/29Jul86>
;______________________________________________________________________
;
; FoundEx
; An exception exists for this particular keystroke. Process it appropriately.
;______________________________________________________________________
FoundEx ; <C201/07Oct86>
MOVE.B (A0)+, D1 ; Get the operand
BPL.S @notXORKey ; Skip if not <A274/27Oct86>
MOVEQ #0, D2 ; Clear out D2
MOVE.B D3, D2 ; Copy virtual keycode to D2
LSR.W #3, D2 ; Divide by 8 for byte offset
BTST D3, KeyBits(A2, D2) ; Get current key state
SEQ D0 ; Invert and put in D0
@notXORKey ; <A274/27Oct86>
MOVEQ #$F, D2 ; Prepare mask for ADB op
AND.B D1, D2 ; D2 is ADB op w/o net address
BEQ.S KbdDone ; If ADB op = 0 (Bus Reset), ignore key
TST.B KNoADBOp(A2) ; See if we should even do this
BNE NoExcept ; Skip if not
MOVEM.L D0/A1, -(SP) ; Save D0 & A1
MOVE.L A0, -(SP) ; Data address = mask
CMP.B #TalkCmd, D2 ; Is it a talk command?
BGE.S @kbdTalk ; Skip if so <A274/27Oct86>
PEA KbdBufFree ; Completion routine = KbdBufFree
BRA.S @kbdBufAlloc ; <A274/27Oct86>
@kbdTalk ; <A274/27Oct86>
PEA KbdListen ; Completion Routine = KbdListen
@kbdBufAlloc ; <A274/27Oct86>
LEA KNumBufs(A2), A1 ; Point to the number of available buffers
MOVE.B (A1)+, D1 ; Get the number of buffers
BEQ.S @kNoBufAvail ; Skip if none available <A274/27Oct86>
SUBQ.W #1, D1 ; Turn it into a zero based count
@kBufLoop ; <A274/27Oct86>
TST.B (A1)+ ; Is the buffer busy?
BEQ.S @kGotABuf ; No, Go use it <A274/27Oct86>
LEA KBufLen-1(A1), A1 ; Point to the next one
DBRA D1, @kBufLoop ; Go around again <A274/27Oct86>
BRA.S @kNoBufAvail ; It's a loss <A274/27Oct86>
@kGotABuf ; <A274/27Oct86>
MOVE.B D0, -1(A1) ; Store the up/down state in the busy info
BSET #1, -1(A1) ; Make sure it shows up as busy
MOVE.L A1, -(SP) ; Buffer Address
MOVE.B (A0), D1 ; Get length of source string
CMP.B #8, D1 ; Greater than 8?
BLS.S @kStrCopyLoop ; If not, no problem <A274/27Oct86>
MOVEQ #8, D1 ; Copy only the first 8 to avoid trashing mem
@kStrCopyLoop ; <A274/27Oct86>
MOVE.B (A0)+, (A1)+ ; Start copying the string
DBRA D1, @kStrCopyLoop ; Repeat D1+1 times <A274/27Oct86>
MOVE.W D3, D0 ; Get the FDB Address
CLR.B D0 ; Clear out the low byte
LSR.W #4, D0 ; Shift it down to form high nibble of ADB Command
OR.B D2, D0 ; Include low op nibble
MOVE.L SP, A0 ; Point to parameter block
_ADBOp ; Pray that everything is OK
BNE.S @kOpFailed ; Branch if not <A274/27Oct86>
ADDQ.L #4, SP ; Pop Buffer Address
@kNoBufAvail ; <A274/27Oct86>
ADDQ.L #8, SP ; Pop Completion and Data Address
MOVEM.L (SP)+, D0/A1 ; Restore D0 & A1
BRA NoExcept ; Finish dealing with the keystroke
@kOpFailed ; <A274/27Oct86>
MOVE.L (SP)+, A1 ; Get the buffer address
CLR.B -1(A1) ; Mark it as not busy
BRA.S @kNoBufAvail ; Punt <A274/27Oct86>
; End FoundEx <C201/07Oct86>
;______________________________________________________________________
;
; Routine: KbdListen
; Arguments: D0.B ADB Command
; D1.L DeviceType, OrigAddr, ADBAddr, Unused (byte order)
; A0 ADB Buffer Address
; A1 ADB Completion Routine Address (= KbdListen)
; A2 ADB Data Address
; Output: None
; Function: Sets or clears bits in mask pointed to by A2 in buffer pointed
; to by A0. Used to alter values of registers in ADB devices.
; Side Effects: Trashes A0, A1, A2, D0, D1, D2
;
; Modification history:
; 3 Oct 86 EMT Created
;______________________________________________________________________
KbdListen ; <C201/07Oct86>
MOVE.L A0, A1 ; Copy A0 into A1 so as to avoid trashing A2
MOVEQ #0, D1 ; Clear out D1
MOVE.B (A1)+, D1 ; Get length of buffer
MOVE.B (A2)+, D2 ; Get length of mask
CMP.B D2, D1 ; Is mask length smaller?
BLS.S @notSmall ; Skip if not <A274/27Oct86>
MOVE.B D2, D1 ; Use the mask length instead
@notSmall ; <A274/27Oct86>
; (A2) is a mask for (A0), 0 meaning don't change, 1 meaning clear or set
; depending upon the value of -1(A0).
TST.B -1(A0) ; PL = clear, MI = set
BPL.S @endClrLoop ; <A274/27Oct86>
BRA.S @endSetLoop ; <A274/27Oct86>
@setLoop ; <A274/27Oct86>
MOVE.B (A2)+, D2 ; Get the mask byte
OR.B D2, (A1)+ ; Set the correct bits
@endSetLoop ; <A274/27Oct86>
DBRA D1, @setLoop ; Go around again <A274/27Oct86>
BRA.S @kLoopDone ; <A274/27Oct86>
@clrLoop ; <A274/27Oct86>
MOVE.B (A2)+, D2 ; Get the mask byte
NOT.B D2 ; Invert it
AND.B D2, (A1)+ ; Clear the correct bits
@endClrLoop ; <A274/27Oct86>
DBRA D1, @clrLoop ; Go around again <A274/27Oct86>
@kLoopDone ; <A274/27Oct86>
CLR.L -(SP) ; No data address needed
PEA KbdBufFree ; Completion routine = KbdBufFree
MOVE.L A0, -(SP) ; Use the buffer one more time
MOVE.L SP, A0 ; Point to parameter block
BCLR #2, D0 ; Turn the talk into a listen command
_ADBOp
BNE.S @kLSuccess ; Branch on success <A274/27Oct86>
MOVE.L (SP), A0 ; Get the buffer address
CLR.B -1(A0) ; Mark it as not busy
@kLSuccess ; <A274/27Oct86>
LEA 12(SP), SP ; Pop the parameter block
RTS
; End KbdListen <C201/07Oct86>
;______________________________________________________________________
;
; Routine: KbdBufFree
; Arguments: D0.B ADB Command
; D1.L DeviceType, OrigAddr, ADBAddr, Unused (byte order)
; A0 ADB Buffer Address
; A1 ADB Completion Routine Address (= KbdListen)
; A2 ADB Data Address
; Output: None
; Function: Marks the buffer pointed to by A0 as free.
; Side Effects: None
;
; Modification history:
; 3 Oct 86 EMT Created
;______________________________________________________________________
KbdBufFree ; <C201/07Oct86>
CLR.B -1(A0)
RTS
; End KbdBufFree <C201/07Oct86>
;___________________________________________________________________________
;
;____________________________________________________________________________________
; P019 C570 23Dec86 ABO VInstall atalk:lap.a
; PA073 2Mar87 ABO VInstall atalk:nonres.a
; PAB185 29Jun87 ABO VInstall atalk:nonres.a
; s263 7sep87 bbm VInstall sounddriver
;
; P019 is to fix a rare(!!) bug in lap.a within the MPP driver.
; PB073 Fixes a re-entrancy problem in nonres.a within MPP.
; PAB185 Fixes an NBP lookup bug where if the response comes back too quickly it
; is written to location zero.
;
; If we're doing a VInstall to install MPP's VBL task, change the address to
; one in RAM, where we disable interrupts and then call the real VBL task.
; This makes the test-and-decrement atomic, preventing VBLDeferCnt from ever
; going negative.
;
; If we're doing a VInstall from Nonres, and the queue element we're installing
; is already there, don't install. If we're doing a lookup, skip the first write.
;
; s263 The current sound driver uses low memory as a vbl queue element. A bug occurs
; if sound is active. The low memory queue element is zeroed regardless if there is a
; next element in the queue or not. Thus the machine may hang. The fix forces the
; sound vbl queue element to be last in the queue always.
; pma287 sound manager uses sound manager uses soundactive different than sound driver.
; Thus soundactive could be true with no sound vbl task installed. So now we check for
; an error from vremove, which we should have done in the first place. (This is the
; same patch as S278, which got deleted when PMAB284 was checked in.)
; s481 there was a small window after the vremove where a timer interrupt could happen.
; Since the sound driver services the timer in the vbl task, the code to reinstall the
; vbl task would never happen.
; s483 changed a hardwired number to HiIntMask (see s481).
NewVInstall PROC EXPORT
CalledFrom EQU $1C ; Where we were called from (return addr)
SkipBytes EQU 18 ; No. of bytes to skip write (PAB185)
VBLHnd EQU $43375C ; MPP VBL task address in ROM
ROMVInstall EQU $402C50 ; ROM VInstall address
NRVBLHnd EQU $434232 ; Nonres VBL task address in ROM
tst.b SoundActive ; sound playing? fixes trashed vbl queue <s263>
beq.s @TruVinst ; if not, just do real vinstall <s263>
move.w sr,-(sp) ; Save sr <s481>
ori.w #HiIntMask,sr ; Disable interrupts <s483>
move.l a0,-(sp) ; save new vbl element on stack <s263>
lea SoundVBL,a0 ; point at hertzfeldÕs vbl element <s263>
_VRemove ; remove sound vbl element <s263>
move.l (sp)+,a0 ; get new vbl element back in a0 <s263>
tst.w d0 ; check for error from vremove <pma287>
bne.s @popstatus ; if error then donÕt reinstall sound vbl <s481>
bsr.s @TruVinst ; install new vbl element back in queue <s263>
lea SoundVBL,a0 ; get sound vbl element, and install it <s263>
bsr.s @TruVinst ; install sound vbl element back in queue <s481>
move.w (sp)+,sr ; Restore interrupts <s481>
rts ; <s481>
@popstatus ; <s481>
move.w (sp)+,sr ; Restore interrupts <s481>
@TruVinst ; <s263>
MOVE.L VBLAddr(A0),D1 ; D1 = VBL task address
AND.L MaskBC,D1 ; Mask off high bits to be sure
CMP.L #VBLHnd,D1 ; Called from MPP VBL task?
BNE.S @1 ; Branch if not
PEA NewVBLHnd ; Push address of patch
MOVE.L (SP)+,VBLAddr(A0) ; Set it
@1 CMP.L #NRVBLHnd,D1 ; Called from NBP VBL task?
BNE.S @30 ; Branch if not
; PAB185 start
MOVE.L -4(A0),A2 ; A2 -> queue element from call
CMP #LookupName,CSCode(A2) ; Was it a lookup request?
BNE.S @5 ; Branch if not
TST.B Count(A2) ; Check count
BEQ.S @3 ; Branch if zero (leave alone)
ADDQ.B #1,Count(A2) ; Need to add one since aren't sending now
@3 ADD.L #SkipBytes,CalledFrom(SP) ; Skip past the write
MOVE #1,VBLCount(A0) ; Set to send out real soon
; PAB185 end
@5 MOVE SR,-(SP) ; Save SR
MOVE #$2600,SR ; Disable interrupts
LEA VBLQueue+QHead,A2 ; A2 -> Head of VBL queue
@10 TST.L (A2) ; Done?
BEQ.S @20 ; Branch if so
MOVE.L (A2),A2 ; A2 -> next element
CMP.L A2,A0 ; Matches the one we're installing?
BNE.S @10 ; Loop if not
MOVE (SP)+,SR ; Restore SR
MOVEQ #0,D0 ; Indicate no error
RTS ; Return (already installed)
@20 MOVE (SP)+,SR ; Restore SR
@30 JMP ROMVInstall ; Jump to ROM VInstall code
NewVBLHnd MOVE SR,-(SP) ; Save interrupt status
MOVE #$2600,SR ; Interrupts off (SCCLockout)
JSR VBLHnd ; Call VBL task
MOVE (SP)+,SR ; Restore interrupts
RTS ; That's it
;___________________________________________________________________________
; P021 C491 08Dec86 DAF GetWVariant WindowMgr2.a:GetWVariant
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 08Dec86 #P021 (GetWVariant) (GetWVariant)
;
;
; function GetWVariant ( someWindow : WindowPtr ) : integer;
;
; GetWVariant returns the variant code of the windowRecord pointed at by
; someWindow. The value returned is an integer even though variants
; are currently only 4 bits as word params on the stack are easier to
; handle
;
GetWVariant PROC EXPORT
MOVE.L (SP)+,A0 ; get the return address
MOVE.L (SP)+,A1 ; get windowPtr
MOVEQ #$0F,D0 ; trim to 4 bits, word length
AND.B WindowDef(A1),D0 ; get the variant code
MOVE.W D0,(SP) ; return the result
JMP (A0) ; return to caller
;___________________________________________________________________________
; P022 C491 08Dec86 DAF GetCVariant ControlMgr1.a:GetCVariant
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 08Dec86 #P022 (GetCVariant) (GetCVariant)
;
;
; function GetCVariant ( whichControl : controlHandle ) : integer;
;
; GetCVariant returns the control variant code of the control whose
; handle is whichControl. Variant codes are 4-bit values returned
; right-justified in the word result. In case you are wondering
; the result is word rather than byte because it's less complicated
; for this stack-based routine, and the variant is passed to the
; defprocs as a word.
GetCVariant PROC EXPORT
MOVE.L (SP)+,A1 ; get the return address
MOVE.L (SP)+,A0 ; get windowPtr
MOVE.L (A0),A0 ; get ctl ptr
MOVEQ #$0F,D0 ; lo nybble only
AND.B ContrlDefHandle(A0),D0 ; get selector parameter
MOVE.W D0,(SP) ; return result
JMP (A1) ; and return to caller
;___________________________________________________________________________
; PMA207 Cxxx 17Jul87 EHB PackBits
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 17Jul87 #PMA207 (PackBits) (PackBits)
;
; This patch allows scanLines > 127 bytes to be packed using packBits.
PatchPMA207 PROC EXPORT
ENDPROC ; Important: PackBitsPatch.a contains globals which must be
; outside of any PROC.
INCLUDE 'PackBitsPatch.a'
;___________________________________________________________________________
; PA061 C628 25feb87 bbm added new trap rGetResource.
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 25feb87 #PA061 (rGetResource) (rGetResource)
;
; Routine: FUNCTION rGetResource(theType: ResType; theID: INTEGER): Handle; <C628>
;
; Arguments: 10(A6) (input.L) resource type
; 8(A6),A0(input.W) resource ID
; 14(A6) (output.L) resource handle
;
; Called By: A-trap through dispatcher
; Calls: GetResource
;
; Function: do a normal GetResource without the rom map; if that fails,
; do GetResource with the rom map inserted.
;
; NOTE: _GetResource expects a specific items on the stack when called.
; This routine depends heavily on that stack. Below is a picture
; of the stack just before the _GetResource trap is executed
; (starting in the middle of the stack and ending at the top of stack,
; or starting in high memory and decending down in memory).
;
; handle 4 bytes
; type 4 bytes (E bytes back on stack after < subq #4,sp >)
; ID 2 bytes (C bytes back on stack after < subq #4,sp >)
; rtn addr 4 bytes (8 bytes back on stack after < subq #4,sp >)
; rtn addr 4 bytes (4 bytes back on stack after < subq #4,sp >)
; handle 4 bytes (0 bytes back on stack after < subq #4,sp >)
; type 4 bytes
; ID 2 bytes
grStFr equ $0E ; size of the stack frame. (see note above)
NewrGetResource PROC EXPORT ;
clr.b ROMMapInsert ; make sure we donÕt use rom map
bsr.s @getrsrc ;
bne.s @exit ; if handle is not zero, then we donÕt check rom
st.b ROMMapInsert ; else make sure we use rom map
bsr.s @getrsrc ;
@exit ; std exit to strip the stack
move.l (sp)+,a0 ; strip off the return address into a0 <C669>
addq #6,sp ; strip off type and ID
jmp (a0) ; and return through a0
@getrsrc ; go do GetResource
move.b resload,ROMMapInsert+1 ; set temp value of resload to current resload
subq #4,sp ; save room for another handle (see note above)
move.l grStFr(sp),-(sp) ; push type again
move.w grStFr+2(sp),-(sp) ; push ID again
_GetResource ;
move.l (sp)+,grStFr(sp) ; push the handle we got back into the area
; the user saved for the handle and set ccÕs
rts ;
ENDPROC ; NewrGetResource
;____________________________________________________________________________________
; PA081 03Mar87 SHF SCSICmd SCSIMgr.a:SCSICmd
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 03Mar87 #PA081 (SCSICmd) (SCSICmd)
;
; This is a SCSI Manager fix for the timeout waiting for Command phase
; (the old value was found to be too short for some disk drives).
;
;
SCSIPatch PROC EXPORT
EXPORT NewSCSIGet,NewSCSICmd, NewSCSIRead, NewSCSIRBlind, NewSCSIWrite, NewSCSIWBlind
ROMGetArb EQU $41A2A0 ; "bsr Arbitrate" entry point <PMAB466/JWK>
ROMGetExit EQU $41A2AA ; finish the SCSIGet call <PMAB466/JWK>
ROMCmdDone EQU $41A2E4 ; finish the SCSI command
ROMWfnReq EQU $41A898 ; wait for *REQ to go away
ROMWfReq EQU $41A8C8 ; wait for *REQ
zeroReg EQU d7 ; SCSI Manager convention
; should be in a separate "SCSIMgrPrivate" include file <PMAB466/JWK>
numSCSIVect EQU 24 ; max. number of selectors <C936/06Nov87> <PMAB466/JWK>
jmpTblSize EQU numSCSIVect*4 ; <C936/06Nov87> <PMAB466/JWK>
G_State EQU jmpTblSize+1 ; byte <PMAB466/JWK>
;--------------------------------------------------------------------------
;
; FUNCTION SCSICmd(Buffer: Ptr, Count: INTEGER): INTEGER;
; (10) (8) (14)
;
; Send the target the given command. Returns 0 for success, or error.
;
NewSCSICmd
move.l 10(a6),a2 ; get the cmdblk address
move.w 8(a6),d2 ; get the length
; calculate a timeout of 256 ms (was 16 ms)
moveq.l #0,d3 ; clear upper word
move.w TimeSCCDB,d3 ; timing constant (1 ms.)
lsl.l #8,d3 ; multiply by 256
move.l d3,d4 ; set up d4 as high word
swap d4
move.b #iCD,sTCR+WrOffs(a3) ; match on cmd+write phase
move.w d3,d1 ; low word of count
move.w d4,d5 ; high word of count
jsr ROMWfReq ; wait for *REQ
bne.s CmdDone ; no *REQ
btst.b #bPM,sBSR(a3) ; does the phase still match?
bne.s CmdDbra ; branch if phase is OK
moveq.l #scPhaseErr,d0 ; else report it
bra.s CmdDone ; return the error
NextByte
move.b (a2)+,sODR+WrOffs(a3) ; load a command byte
move.b #iDB,sICR+WrOffs(a3) ; assert the data bus
move.w d3,d1 ; low word of count
move.w d4,d5 ; high word of count
jsr ROMWfReq ; wait for *REQ
bne.s CmdDone ; no *REQ
move.b #iACK+iDB,sICR+WrOffs(a3) ; set *ACK
move.w d3,d1 ; low word of count
move.w d4,d5 ; high word of count
jsr ROMWfnReq ; wait for *REQ to go away
bne.s CmdDone ; didn't go away
move.b zeroReg,sICR+WrOffs(a3) ; deassert *ACK and *DB
CmdDbra
dbra d2,NextByte ; do this for all bytes
moveq.l #0,d0 ; return success
CmdDone
jmp ROMCmdDone ; finish up in the ROM
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
;
; PMAB466 13Apr88 JWK SCSIGet SCSIMgr.a
;
; This cleans up the SCSIGet arbitration scheme. A "bset" instruction is used to
; test-and-set the SCSI Mgr's G_State global state variable. The ROM implementation
; could allow two processes into the SCSI Mgr code.
;
NewSCSIGet
bset.b #0,G_State(a4) ; mark SCSI Mgr state as "busy" <PMAB466/JWK>
beq.s @1 ; if zero, SCSI Mgr was free <PMAB466/JWK>
moveq.l #scMgrBusyErr,d0 ; SCSI Mgr is busy <PMAB466/JWK>
jmp ROMGetExit ; get out <PMAB466/JWK>
@1
jmp ROMGetArb ; jump to "bsr Arbitrate" and continue <PMAB466/JWK>
;____________________________________________________________________________________
; PMA211 20Jul87 SHF SCSIRead,SCSIRBlind,SCSIWrite,SCSIWBlind SCSIMgr.a:(see previous)
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 20Jul87 #PMA211 (SCSIRead,SCSIRBlind,SCSIWrite,SCSIWBlind) (SCSIRead,SCSIRBlind,SCSIWrite,SCSIWBlind)
;
; This fixes the scLoop bug in the TIB interpreter where the interpretation was
; being aborted when the count field decremented to 0.
;
;--------------------------------------------------------------------------
;
; FUNCTION SCSIRead(Control:Ptr): INTEGER; (polled read and write)
; FUNCTION SCSIWrite(Control:Ptr): INTEGER;
; FUNCTION SCSIRBlind(Control:Ptr): INTEGER; (blind read and write)
; FUNCTION SCSIWBlind(Control:Ptr): INTEGER;
; (8) (12)
;
; This is the heart of the SCSI data transfer code, which includes the
; Transfer Information Block (TIB) interpreter.
;
ROMDataXfer EQU $41A51C ; main data transfer (read/write)
ROMDataEnd EQU $41A376 ; finish up after TIB interpretation
NewSCSIWBlind
bset #15,d4 ; set blind mode flag
NewSCSIWrite
st d4 ; set flag for writes
bra.s DataCommon
NewSCSIRBlind
bset #15,d4 ; set blind mode flag
NewSCSIRead ; only start for reads
move.b #iIO,sTCR+WrOffs(a3) ; match Data In phase <PMA211>
move.b #iDMA,sMR+WrOffs(a3) ; DMA mode <PMA211>
move.b zeroReg,sIDMArx+WrOffs(a3) ; start DMA for a read <PMA211>
DataCommon
moveq.l #bDMAR,d3 ; bit for DREQ test used in DataXFER
move.l 8(a6),a1 ; get the control block pointer
bra.s exec ; branch into loop to continue
c_compare
move.b #1,d4 ; this means compare to DataXFER
; FALL THROUGH to c_inc
c_inc ; INC Addr,count
jsr ROMDataXFER ; move some data
bne.s data_end
add.l d2,scParam1(a1) ; increment the pointer
; FALL THROUGH to next_cmd
next_cmd
c_nop ; also NOP, just skip the command
add.w #SCSIZE,a1 ; move the command pointer
exec
move.w scOpcode(a1),d0 ; get the function opcode
move.l scParam1(a1),a2 ; get the generic address
move.l scParam2(a1),d2 ; get the generic count
subq.w #5,d0
beq.s c_loop ; 5
addq.w #4,d0
beq.s c_inc ; 1
subq.w #1,d0
beq.s c_noinc ; 2
subq.w #5,d0
beq.s c_stop ; 7
addq.w #4,d0
beq.s c_add ; 3
subq.w #1,d0
beq.s c_move ; 4
subq.w #2,d0
beq.s c_nop ; 6
subq.w #2,d0
beq.s c_compare ; 8
moveq.l #scBadParmsErr,d0 ; garbage parameters...
bra.s data_end
c_noinc ; NOINC addr,count
jsr ROMDataXFER ; move some data
beq.s next_cmd ; & process next command
bra.s data_end
c_add ; ADD addr,data
add.l d2,(a2) ; the count added to the where
bra.s next_cmd
c_move ; MOVE addr1,addr2
move.l d2,a0
move.l (a2),(a0) ; simple enough
bra.s next_cmd
c_loop ; LOOP relative addr,count
subq.l #1,d2 ; drop the count
beq.s next_cmd ; if count = 0, go to next instruction
move.l d2,scParam2(a1) ; put the count back for next time
add.l a2,a1 ; modify the command pointer
bra.s exec ; and process the next command
c_stop
moveq.l #0,d0 ; indicate no error
data_end
jmp ROMDataEnd
;_________________________________________________________________________________________ <50> djw
; Beginning code for Quantum 7.9 ROM fix
;
; Detailed description of the Quantum problem and solution:
;
; Quantum drives with the firmware version 7.9, has a problem with loosing the last byte
; of a block during a multi-block write. The problem occurs when the time between blocks
; written to the SCSI bus on the CPU side, is greater than 482 microseconds. This may
; occur in situations where there are a lot of interrupts. When conditions are right and
; the problem happens, the last byte of the previous block (in a multi-block transaction),
; is "eaten" by the drive. Any checksum or CRC calculated by the drive is correct,
; because the drive calculates it after the byte has been corrupted. This problem is
; especially frequent when email packages are installed on the Mac, since they generate
; a lot of interrupts which take a long time. This problem only occurs during fast
; writes in the SCSI manager (pseudo-dma mode).
;
; The way the SCSI manager currently works is it gets a TIB packet which contains the
; instructions on how to talk to a particular device. Included in the TIB is when to
; re-synchronize with the drive by waiting for a *REQ. When we see *REQ, the SCSI
; manager then begins the next TIB data transfer instruction and loads a byte of data
; into the 53C80's output register. After the first byte is "manually" sent, the
; hardware handshaking automatically takes care of the *REQ and *ACK handshaking. When
; the TIB write transfer is complete, pseudo-dma is disable, which releases *ACK,
; completing the handshake. This allows the target to assert *REQ when it is ready.
;
; The window of vulnerability is between the last byte of the previous block and the
; first byte of the next block. More correctly, it is between the rising edge of *ACK
; and the falling edge of the next *ACK. Because we release *ACK to synchronize, an
; interrupt may come in and delay the next transfer.
;
; The solution to the problem is to pre-load a data byte into the 53C80's data output
; register before we release *ACK. There are two ways of releasing *ACK: disable pseudo
; dma, and write a byte to the data output register. Leaving pseudo-dma enabled through
; the entire TIB will mean that whenever a *REQ occurs, there will be data available in
; the output register. This means there will be no delay between bytes because the
; hardware is not subject to interrupt delays.
;
; This patch therefore involves patching the TIB interpreter and the fast write routine
; in the SCSI manager. There are five versions of the SCSI manager to patch: Mac Plus,
; SE, Mac II, Portable, and IIci.
;
;_________________________________________________________________________________________
; QuantumWBlindSE - patch to NewSCSIWBlind
;
; This code replaces the original SCSIWBlind entry point. The new entry for blind
; writes enables pseudo-dma on a per-transaction basis. Pseudo-dma was previously
; enabled only on a per-TIB-instruction basis. We completely patch out the existing
; ROM and system patch code for blind writes. This includes the TIB interpeter and
; the blind data transfer routine.
;
; Input: reg a3 = base of SCSI read addr
; a6 = SCSI stack frame
; d7 = zero
;
Opt noclr ; set optimization level to no clr's <50> djw
Export QuantumWBlindSE
QuantumWBlindSE
maxOpcode Equ 8 ; max TIB opcodes (from SCSIPriv.a) <50> djw
; This is the entry to the TIB interpeter for blind writes. Enable pseudo-dma mode
; for the duration of the write transaction.
move.b d7,sTCR+WrOffs(a3) ; set to match data out phase (to zero)
move.b #iDMA,sMR+WrOffs(a3) ; enable DMA in mode register
move.b #iDB,sICR+WrOffs(a3) ; assert data bus in initiator command reg
move.b d7,sDMAtx+WrOffs(a3) ; start write DMA
; Start of TIB interpreter
@dataCommon
move.l 8(a6),a1 ; get the TIB pointer
bra.s @exec ; tighten loop by branching first
@c_inc
bsr.s FastWriteFix ; go to write blind routine
bne.s @data_end ; if error, bail out
add.l d1,scParam1(a1) ; increment the pointer
; FALL THROUGH to @next_cmd ; continue
@next_cmd
@c_nop ; also NOP, just skip the command
add.w #scSize,a1 ; point to the next TIB instruction
; FALL THROUGH to @exec
@exec
move.w scOpcode(a1),d1 ; get the function opcode
move.l scParam1(a1),a2 ; get the generic address
move.l scParam2(a1),d2 ; get the generic count
cmp.w #maxOpcode,d1 ; valid opcode ?
bhi.s @c_badop ; return err if not
add.w d1,d1 ; convert to table index
jmp @JmpTable(pc,d1.w) ; jump to routine for opcode
@JmpTable
bra.s @c_badop ; 0 is not a valid opcode
bra.s @c_inc ; 1
bra.s @c_noinc ; 2
bra.s @c_add ; 3
bra.s @c_move ; 4
bra.s @c_loop ; 5
bra.s @c_nop ; 6
bra.s @c_stop ; 7
nop ; 8 not valid
; fall through to @c_badop
@c_badop
moveq.l #scBadparmsErr,d0 ; bad opcode
bra.s @data_end
@c_noinc ; NOINC addr,count
bsr.s FastWriteFix ; go to write blind routine
bne.s @data_end ; if error, exit
bra.s @next_cmd ; else process next command
@c_add ; ADD addr,data
add.l d2,(a2) ; the count added to the where
bra.s @next_cmd ; process the next command
@c_move ; MOVE addr1,addr2
move.l d2,a0 ; get the destination address
move.l (a2),(a0) ; simple enough
bra.s @next_cmd ; process the next command
@c_loop ; LOOP relative addr,count
tst.l d2 ; check for zero loop count
beq.s @next_cmd ; if count is already zero, quit loop
subq.l #1,d2 ; drop the count
move.l d2,scParam2(a1) ; put the count back for next time
beq.s @next_cmd ; if count exhausted, don't loop <C859>
add.l a2,a1 ; modify the command pointer
bra.s @exec ; and process the next command
@c_stop
moveq.l #noErr,d0 ; indicate no error
; FALL THROUGH to @data_end ; <C846>
@data_end
jmp (ROMDataEnd) ; continue in ROM <50> djw
;_________________________________________________________________________________________
; FastWriteFix - patch to FastWrite
;
; This code replaces the low level data transfer routine for fast writes in the SCSI
; manager. It is rewritten to assume psuedo-dma is always on, and to do the device
; synchronization (looking for *REQ and *DRQ), after loading a data byte into the
; output register of the 5380. We don't have to worry about zero-byte transfers. They
; are weeded out in the calling routine (Transfer).
;
; Entry: d2 = number of bytes to transfer
; a2 = ptr to data buffer to transfer
; a3 = base addr of NCR 53C80
; a4 = ptr to SCSI globals
;
; Exit: d1 = number of bytes actually transfered. This value is only good if
; the transfer was good with no errors. It is inaccurate when an
; error aborts the transfer.
FastWriteFix
OldBusVct Equ -8
@savedregs Reg d2-d4/a1-a2/a5
; Setup for the transfer by installing our bus exception handler and saving
; registers.
movem.l @savedregs,-(sp)
lea.l sBSR(a3),a1 ; a1 = sBSR(a3) by convention
lea @Done,a5 ; set a5 as return addr from bus error
move.l BusErrVct,OldBusVct(a6) ; keep old vector
lea @BusErrHandler,a0 ; get addr of exception handler
move.l a0,BusErrVct ; install it in exception table
move.l SCSIHsk,a0 ; point to addr for pseudo-dma (hhsk)
adda.l #wroffs,a0 ; add in the write offset
moveq.l #noErr,d0 ; assume no error
move.l d2,d1 ; make a copy of the count - is it zero ?
beq @Done ; no bytes to xfer - done
; Pre-load the NCR 53C80's output register with a byte of data. If we are in
; the middle of a multi-block write, *ACK is currently asserted. Writing a byte
; to the output register will release *ACK, completing the handshaking, allowing
; the target to assert *REQ.
sub.l #1,d2 ; dec number of bytes to xfer
move.b (a2)+,(a0) ; write data byte to output register
; With *ACK released, determine if the target is in sync. We cannot look for
; *REQ to be asserted, because the target may have already accepted the data byte
; and released *REQ at this point. We can sync on DRQ which will signal when
; the NCR 53C80 is ready to accept a data byte, meaning a *REQ from the target
; must have already occurred and our data byte was taken.
@syncWait
btst.b #bDMAR,(a1) ; check bus & status reg for DRQ
bne.s @doWrite ; DRQ present - sync-ed up so proceed
btst.b #bREQ,sCSR(a3) ; no DRQ - is *REQ present ?
beq.s @syncWait ; no *REQ yet - wait for sync
btst.b #bPM,(a1) ; with *REQ, check phase lines
bne.s @syncWait ; still in data out phase - wait
moveq.l #0,d1 ; out of phase - did not xfer any bytes
moveq.l #scPhaseErr,d0 ; return error
bra @Done ; exit
; Perform the write to the SCSI chip. First align the bytes to words, then
; align them to 32 byte chunks. Transfer the bulk of the data in 32 byte
; blocks.
; Reg d2.l = number of bytes to move
@doWrite
cmpi.l #3,d2 ; check for very short copy
bls.s @veryShort ; skip alignment if very short
move.l a2,d0 ; get addr of data buffer
andi.l #$00000003,d0 ; check for long word alignment
beq.s @Aligned ; if no alignment needed
subq.l #4,d0 ; bias by 4 to get correct index
add.l d0,d2 ; adjust the byte count (d0 = neg)
add.l d0,d0 ; adjust to word index
jmp @Aligned(pc,d0.w) ; do the alignment
move.b (a2)+,(a0) ; move a byte
move.b (a2)+,(a0) ; move a byte
move.b (a2)+,(a0) ; move a byte
@Aligned
move.l d2,d4 ; save tail byte count
lsr.w #2,d2 ; adjust to number of longs to move
moveq.l #7,d0 ; mask for starting index
and.l d2,d0 ; number of long words to move first
neg.w d0 ; negate to index backwards
add.w d0,d0 ; d0 = convert to index by 6 byte entries
move.w d0,d3 ; ...d3 = original value*2
add.w d0,d0 ; ...d0 = original value*4
add.w d3,d0 ; ...d0 = original value*6
lsr.l #3,d2 ; number of 32 byte blocks to move
move.l d2,d3 ; get number of 32*64K byte blks to move
swap d3 ; count in low word
jmp @CopyStart(pc,d0.w) ; jump into the loop
@CopyLoop move.l (a2)+,d0 ; ...fill d0 with 4 bytes
movep.l d0,0(a0) ; ...write 4 bytes to SCSI port
move.l (a2)+,d0 ; do this for 32 bytes
movep.l d0,0(a0)
move.l (a2)+,d0
movep.l d0,0(a0)
move.l (a2)+,d0
movep.l d0,0(a0)
move.l (a2)+,d0
movep.l d0,0(a0)
move.l (a2)+,d0
movep.l d0,0(a0)
move.l (a2)+,d0
movep.l d0,0(a0)
move.l (a2)+,d0
movep.l d0,0(a0)
@CopyStart dbra d2,@CopyLoop ; loop in chunks of 32 bytes
dbra d3,@CopyLoop ; loop in chunks of 32*64K bytes
andi.l #$00000003,d4 ; check for tail alignment
move.l d4,d2 ; d2 = number of bytes remaining
@veryShort
neg.w d2 ; negate to index backwards
add.w d2,d2 ;
jmp @Remaining(pc,d2.w) ; write remaining bytes
move.b (a2)+,(a0) ; move a byte
move.b (a2)+,(a0) ; move a byte
move.b (a2)+,(a0) ; move a byte
@Remaining
; Before exiting this routine, make sure that the peripheral has actually accepted
; the data byte. Wait for a DRQ (meaning the SCSI chip is ready for another byte)
; before exiting.
@DoneWait
moveq.l #noErr,d0 ; set good return
btst.b #bDMAR,(a1) ; check for DRQ (a1 = sBSR(a3))
bne.s @Done ; if DRQ, peripheral got the byte
btst.b #bREQ,sCSR(a3) ; no DRQ - is *REQ present ?
beq.s @DoneWait ; no *REQ yet - wait for it
btst.b #bPM,(a1) ; are we still in phase ?
bne.s @DoneWait ; if so, keep waiting
@Done
move.l OldBusVct(a6),BusErrVct ; restore previous Bus Error vector
movem.l (sp)+,@savedregs
tst.w d0 ; set the condition codes
rts ; we're done
;_________________________________________________________________________________________
; BusErrHandler - SCSI manager's bus exception handler
;
; Hardware handshaking data transfers require that the target peripheral be ready to
; receive or transmit a long word of data within 16 microseconds. Failure of the
; target to keep up will result in a bus error. In 68000 machines, no retries are
; possible so the transfer fails. It is up to the driver to retry.
;
; Determine whether the bus error belongs to the SCSI manager by examining the fault
; address. It should be an offset from the SCSIHsk base.
;
; Entry: a3 = base address of SCSI chip
; a5 = address to return to if bus exception
; a6 = SCSI mgr local stack frame ptr
;
; Output: d0 = error code
;
@BusErrHandler
move.l d0,-(sp) ; save d0
; Access to a number of SCSI addresses could cause a bus exception. Mask off the low
; bits of the fault address to get the base address. If it matches the SCSI chip's
; base address
moveq.l #$ffffff9c,d0 ; mask = $ffffff9c
and.l 2(sp),d0 ; clear variable bits of the fault address
cmp.l SCSIHsk,d0 ; was it a SCSI chip access ?
beq.s @ourErr ; if so, start processing the bus error
; Bus exception caused by someone else - call original exception handler
move.l (sp)+,d0 ; restore d0
move.l OldBusVct(a6),-(sp) ; jump to old bus error handler
rts
; Pop group 0 bus exception stack frame from stack and replace it with a normal
; group 1 (3 word) frame. Place a new return address in the exception frame and RTE.
@ourErr
move.w 8(sp),d0 ; get sr from stack
adda.w #7*2,sp ; dispose of the 7-word frame
move.l a5, -(sp) ; new return address
move.w d0,-(sp) ; sr value
; Determine whether this was a phase change or a device timeout from hardware handshaking
moveq.l #scBusTOErr,d0 ; assume a slow peripheral
btst.b #bREQ,sCSR(a3) ; is *REQ present ?
beq.s @ErrorDone ; no *REQ - assume timeout error
btst.b #bPM,sBSR(a3) ; phase change?
bne.s @ErrorDone ; no phase change
moveq.l #scPhaseErr,d0 ; return phase change error
@ErrorDone
rte ; 'return' from the fake exception
Endp
Opt all ; set optimization back to preset level <50> djw
;____________________________________________________________________________________
; PAB87 06Mar87 CSL patch out the JcrsrTask to support absolute cursor position.
; The whole Jcrsrtask routine is replaced by the patch below.
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 06Mar87 #PAB87 (JcrsrTask) (JcrsrTask)
;
CrsrPtch PROC EXPORT
;
; ===================================================================
; Constants. Size of the mapping table.
; ===================================================================
;
MaxL EQU 8 ; Maximum value of L
;FDBByte0 EQU $164
;FDBByte1 EQU $165
;
; ===================================================================
; Globals. First words of this resource.
; ===================================================================
;
Cnt EQU 0 ; word: number of valid error deltas
MaxCnt EQU Cnt+2 ; word: limit on number of error deltas
Err7 EQU MaxCnt+2 ; word: time-7 error magnitude
Err6 EQU Err7+2 ; word: time-6 error magnitude
Err5 EQU Err6+2 ; word: time-5 error magnitude
Err4 EQU Err5+2 ; word: time-4 error magnitude
Err3 EQU Err4+2 ; word: time-3 error magnitude
Err2 EQU Err3+2 ; word: time-2 error magnitude
Err1 EQU Err2+2 ; word: time-1 error magnitude
Error EQU Err1+2 ; word: accumulated error
GSize EQU Error+2
;
;
; ===================================================================
; Code. @MouseMap+EntryOff
; ===================================================================
;
TST.B CrsrNew ; Mouse changed?
BEQ Done ; No É return
TST.B CrsrBusy ; Cursor locked?
BNE Done ; Yes É return
;
TST.B CrsrCouple ; Cursor coupled to mouse?
BEQ NoComp ; No É skip computation <DSV>
;
MOVE.W MTemp+H,D0 ; Find ÆMx
SUB.W RawMouse+H,D0
;
MOVE.W MTemp+V,D1 ; Find ÆMy
SUB.W RawMouse+V,D1
;
MOVE.W D0,D2 ; x := |ÆMx|
BGE.S AbsX1
NEG.W D2
AbsX1
;
MOVE.W D1,D3 ; y := |ÆMy|
BGE.S AbsY1
NEG.W D3
AbsY1
;
move.l MickeyBytes,a0 ; <10/7/86 SMH> get globals
CMP.W D2,D3 ; D3 := magnitude(x,y)
BLS.S MagDone
EXG D2,D3
MagDone
ASR.W #1,D3
ADD.W D2,D3
;
; *** BEGIN NEW ***
;
BNE.S DoComp ; Zero magnitude É donÕt compute ***
MOVE.W #1,Cnt(A0) ; No hits ***
CLR.W Error(A0) ; No errors ***
BRA DoPin ; Update the cursor ***
DoComp
;
MOVEM.L D4-D5,-(A7) ; Save off registers
MOVE.W Cnt(A0),D4 ; D4 is the number of samples
CMP.W MaxCnt(A0),D4 ; Is Count less than MaxCnt
BGE.S CountOK
ADD.W #1,Cnt(A0) ; Yes É we will have one more error
CountOK
;
MOVE.W D3,D5 ; Magnitude at current time
;
MOVE.W D4,D2 ; Get Count
SUB.W #1,D2 ; Index into JTab
ASL.W #1,D2 ; REQUIRES BRA.SÕs IN JUMP TABLES
JMP JTab(PC,D2.W) ; Jump to the right code per Count
;
JTab
BRA.S E1 ; Count = 1
BRA.S E2 ; Count = 2
BRA.S E3 ; Count = 3
BRA.S E4 ; Count = 4
BRA.S E5 ; Count = 5
BRA.S E6 ; Count = 6
BRA.S E7 ; Count = 7
; *** BRA.S E8 ; Count = 8 ***
;
E8 ADD.W Err7(A0),D5 ; Accumulate time-7 magnitude
;
E7 ADD.W Err6(A0),D5 ; Accumulate time-6 magnitude
MOVE.W Err6(A0),Err7(A0) ; Shift out time-6 magnitude
;
E6 ADD.W Err5(A0),D5 ; Accumulate time-5 magnitude
MOVE.W Err5(A0),Err6(A0) ; Shift out time-5 magnitude
;
E5 ADD.W Err4(A0),D5 ; Accumulate time-4 magnitude
MOVE.W Err4(A0),Err5(A0) ; Shift out time-4 magnitude
;
E4 ADD.W Err3(A0),D5 ; Accumulate time-3 magnitude
MOVE.W Err3(A0),Err4(A0) ; Shift out time-3 magnitude
;
E3 ADD.W Err2(A0),D5 ; Accumulate time-2 magnitude
MOVE.W Err2(A0),Err3(A0) ; Shift out time-2 magnitude
;
E2 ADD.W Err1(A0),D5 ; Accumulate time-1 magnitude
MOVE.W Err1(A0),Err2(A0) ; Shift out time-1 magnitude
;
E1 MOVE.W D3,Err1(A0) ; Shift out current magnitude
;
MOVE.W D4,D2 ; Round up the divide
ASR.W #1,D2 ; by half the denominator
ADD.W D2,D5
EXT.L D5 ; Set up for the divide
DIVU D4,D5 ; Find the average magnitude
;
MOVE.W D3,D4 ; Get the original magnitude
SUB.W D5,D3 ; Find distance to average magnitude
ADD.W Error(A0),D3 ; Add on the accumulated error
CMP.W #-1,D3 ; Define -1 div 2 = 0
BNE.S DivOK
CLR.W D3
DivOK ASR.W #1,D3 ; Get half of it
MOVE.W D3,Error(A0) ; Update it
ADD.W D5,D3 ; Desired mag is average+Error
;
CMP.W #255,D5 ; mag := MAX(mag,255)
BLS.S MaxDone
MOVE.B #255,D5
MaxDone
;
move.l MickeyBytes,a0 ; <10/7/86 SMH> get at globals
add #GSize,a0 ; <10/24/86 SMH> point to table
CLR.W D2 ; i := 0
;
Search
ADD.B #1,D2 ; repeat
CMP.B (A0)+,D5 ; i := i+1
BHI.S Search ; until mag ² Table[i]
;
MULS D2,D3 ; D4 := i*(Mag(ÆM)+Error)
;
MULS D3,D0 ; ÆCx := (ÆMx*i*(Mag(ÆM)+Error))/Mag(ÆM)
DIVS D4,D0 ; <<<<<< D3 >>>>>>>
;
MULS D3,D1 ; ÆCy := (ÆMy*i*(Mag(ÆM)+Error))/Mag(ÆM)
DIVS D4,D1 ; <<<<<< D3 >>>>>>>
;
MOVEM.L (A7)+,D4-D5 ; Restore registers
;
; *** END NEW ***
;
ADD.W D0,RawMouse+H ; Update raw mouse location
ADD.W D1,RawMouse+V
;
DoPin
LEA CrsrPin,A0 ; Bounding rect for cursor ***
MOVE.L RawMouse,D0 ; Pin mouse inside rect
BSR.S PinGuts
;
MOVE.L D0,RawMouse ; Update cursor locations
MOVE.L D0,MTemp
;
AND.L MouseMask,D0 ; Do jerky masking to drop low bits
MOVE.L MouseOffset,D1 ; Get the offset
BEQ.S SkipPin ; Skip 2nd pin if not
ADD.L D1,D0 ; Do jerky offset
BSR.S PinGuts ; Pin mouse inside rect again
SkipPin
MOVE.L D0,Mouse ; Actual mouse location
;
Repaint
TST.B CrsrObscure ; Unpaint the cursor
BNE.S Unpainted
_HideCursor ; Hide the cursor
Unpainted
;
CLR.B CrsrNew ; Cursor is fresh
CLR.B CrsrObscure ; Cursor is not obscured
_ShowCursor ; Repaint the cursor
;
; *** BEGIN NEW ***
;
RTS ; Goodbye
;
Done
move.l MickeyBytes,a0 ; <10/7/86 SMH> get globals
MOVE.W #1,Cnt(A0) ; No hits
CLR.W Error(A0) ; No errors
RTS ; Goodbye
;
NoComp
move.l MickeyBytes,a0 ; <10/7/86 SMH> get globals
MOVE.W #1,Cnt(A0) ; No hits
CLR.W Error(A0) ; No errors
BRA.S Repaint ; Update the cursor
;
; *** END NEW ***
;
; ===================================================================
; PinGuts limits the point in D0 to the
; bounding rectangle pointed to by A0.
; ===================================================================
;
PinGuts
CMP.W Left(A0),D0 ; Check left side
BGE.S LeftOK
MOVE.W Left(A0),D0
LeftOK
;
CMP.W Right(A0),D0 ; Check right side
BLE.S RightOK
MOVE.W Right(A0),D0
SUB.W #1,D0
RightOK
SWAP D0 ; Deal with vertical coord
;
CMP.W Top(A0),D0 ; Check top
BGE.S TopOK
MOVE.W Top(A0),D0
TopOK
;
CMP.W Bottom(A0),D0 ; Check bottom
BLE.S BotOK
MOVE.W Bottom(A0),D0
SUB.W #1,D0
BotOK SWAP D0
;
RTS
ENDPROC
;____________________________________________________________________________________
; PMA100 CXXX 10Mar87 DAF FindWindow {TB}WindowMgr3.a
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 10Mar87 #PMA100 (FindWindow) (FindWindow)
;
; FindWindow Patch:
;
; This patch adjusts FindWindow to call the menuBar defProc to hit test the mouse
; point. It works only with the patched menumgr.
;
;
; FUNCTION FindWindow(thePoint: Point; VAR theWindow: WindowPtr): INTEGER;
;
;
FindWindow PROC EXPORT
IMPORT CallMBarProc
FWEntry1 EQU $40C7D2
FWEntry2 EQU $40C7CE
MOVEM.L D1/D3/A3,-(SP) ;save work registers <23-Oct-85 EHB>
LEA 16(SP),A0 ;point to window ptr var <23-Oct-85 EHB>
MOVE.L (A0)+,A1 ;get pointer to windowPtr
CLR.L (A1) ;make it NIL
MOVE.L (A0)+,D3 ;get the mouse point
CLR.W (A0) ;set classification code to zero
;
; first check to see if the point is on the menu bar. It returns - for not in menubar,
; 0 for in menubar, but not in title, or + for in menu Title.
;
MOVEQ #1,D0 ; put hit message in D0 <C424/18Nov86> DAF
MOVE.L D3,D1 ; send point as parameter <C424/18Nov86> DAF
BSR CallMBarProc ; call menuBar defproc <C424/18Nov86> DAF
TST.L D0 ; test the result <C424/18Nov86> DAF
BMI.S NotOnMBar ; if +, then not on bar <C424/18Nov86> DAF
JMP FWEntry2
NotOnMBar JMP FWEntry1
;____________________________________________________________________________________
; PMA100 CXXX 10Mar87 DAF InitWindows {TB}WindowMgr2.a
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 10Mar87 #PMA100 (InitWindows) (InitWindows)
;
; InitWindows Patch:
;
; This patch adjusts InitWindows to call the menuBar defProc when calculating the
; menuBar height and clearing the space. It works only with the patched menumgr.
;
;
; PROCEDURE InitWindows;
;
INITWINDOWS PROC EXPORT
IMPORT CallMBarProc
AllocPort EQU $40BBCE
IWReEntry EQU $40BC4A
LINK A6,#-16 ; make a stack frame
MOVEM.L D3-D5/A3-A4,-(SP) ; save work registers
MOVEQ #7,D0 ; handy bit number <EHB 1/23/85>
BSET D0,DSWndUpdate ; cancel pending PaintBehind <EHB 1/23/85>
BSET D0,AlarmState ; reset alarm parity <EHB 1/23/85>
CLR.B WWExist ; say the window world exists <EHB 1/23/85>
MOVE.L MinusOne,SaveUpdate ;enable update accumulation and erasing
; set up the deskPattern from Sys.resource
SUBQ #4,SP ;make room for function result
MOVE #deskPatID,-(SP) ;push pattern ID of deskPattern
_GetPattern ;tell resource manager to get it
MOVE.L (SP)+,A0 ;get the pattern handle
MOVE.L (A0),A0 ;get pattern pointer
MOVE.L (A0)+,DeskPattern ;init the deskPattern
MOVE.L (A0),DeskPattern+4 ;don't forget 2nd half of it
;
; allocate and init the window manager's port
;
JSR AllocPort
MOVE.L A3,WMGRPORT ;make it the wmgrPort
;
; initialize the screen by blacking out the corners, drawing the menu bar, and then
; filling the rest with the deskPattern.
LEA PortRect(A3),A0 ; get the port's rect
MOVE.L A0,-(SP) ; a copy for building gray region
MOVE.L A0,-(SP) ; and one for painting it gray
LEA TempRect,A4 ; get a temp rect
MOVE.L A4,A1 ; get a copy to trash
MOVE.L (A0)+,(A1)+ ; copy the portRect
MOVE.L (A0),(A1)
MOVE.L A4,-(SP) ; push the temp rect
MOVE.L #$FFFDFFFD,-(SP) ; and make it bigger
_InsetRect ; by 3 pixels on each side
MOVE.L #$00030003,-(SP) ; get a wider pen
_PenSize
MOVE.L A4,-(SP) ; push the port rect
MOVE.L #$00160016,-(SP) ; and a radius for nice rounding
_FrameRoundRect ; and black out the corners
_PenNormal ; fix the pen back up
;
; draw the empty menu bar, leaving the clip region set to the menuBar
_InitMenus ; init the mbar defproc <C168/17Sep86>DAF
MOVEQ #6,D0 ; set up for the height message, no params
BSR CallMBarProc ; execute the defproc,ignoring the result
MOVEQ #0,D0 ; set up for the draw message <DAF 20Aug86>
MOVE.L #-1,D1 ; parameter is -1 for cleared bar only <DAF 20Aug86>
BSR CallMBarProc ; execute the defproc <DAF 20Aug86>
JMP IWReEntry ; return to ROM
;-------------------------------------------------------------------------------------------
;
; Utility -- CallMBarProc
;
; On Entry: d0 lo-word=message number, hi-word=parameter1 <FJL 3Feb87>
; d1 parameter2
; Use: a0
; On Exit: d0 return value
;
; mbResID: comes from menuList
; mbVariant: the low 3 bits of mbResID are the variant
;
; Note that we store the MBDF's Hndl in low memory location MBDFHndl but this is for
; convenience only. We do not count on its being there between calls to this utility.
;
;-------------------------------------------------------------------------------------------
CallMBarProc PROC EXPORT
movem.l d4, -(sp) ; save work register
CLR.L -(SP) ; make room for defproc return <DAF 20Aug86>
MOVE.L MenuList,A0 ; get the menuList head <DAF 20Aug86>
MOVE.L (A0),A0 ; handle->pointer <DAF 20Aug86>
move mbResID(a0), -(sp) ; get resource ID <FJL C428><24Jan87>
andi.w #0007, (sp) ; use low 3 bits only <FJL 24Jan87>
MOVE.W D0,-(SP) ; push the message number <DAF 20Aug86>
swap d0 ; get parameter1 in lo-word
move.w d0, -(sp) ; push parameter1 <FJL 3Feb87>
MOVE.L D1,-(SP) ; push parameter2 <DAF 20Aug86>
;
; get the mbarproc each time we call it instead of counting on low mem to be correct <FJL A/C391>
;
subq #4, sp ; space for return result
move.l #'MBDF', -(sp)
move mbResID(a0), -(sp) ; get resource ID
MOVE.W #MapTRUE,ROMMapInsert ; set flag to load from ROM <DAF 20Aug86>
_GetResource
move.l (sp)+, MBDFHndl
MOVE.L MBDFHndl,A0 ; get the menu bar defproc handle
_HGetState ; get the current state
move.l d0, d4 ; save state in d4
_HLock ; lock it
MOVE.L (A0),A0 ; get a pointer to it
JSR (A0) ; jump to it
; returned from defproc, return handle to previous state before exiting
MOVE.L MBDFHndl,A0 ; get the handle
move.l d4, d0 ; get previous state from d4
_HSetState ; reset previous state
MOVE.L (SP)+,D0 ; get the defproc return
movem.l (sp)+, d4 ; restore work register
RTS ; and return
ENDPROC
;-----------------------------------------------------------------------------
; PABM150 28Mar87 JTC&JAF New SysEnvirons call.
;
; Fix File Date Patch# Routine(s) Fixed Fix Routine(s)
;AppleSystemPatch PatchSEROM.a 28Mar87 #PABM150 (SysEnvirons) (SysEnvirons)
;
INCLUDE 'SysEnvirons.a' ;<PMAB449>
;____________________________________________________________________________________
; PA182 21May87 CSL DiskSelect SonyQDUtil.a:DiskSelect
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 21May87 #PA182 (DiskSelect) (DiskSelect)
;
;
; This patch is to fix the performance of the upper internal floppy drive for SE.
;
RPowerDown EQU $00435316
RomAt1 EQU $00435350
RDiskSelect PROC
TST.W TimeOut(A1) ; timeout pending? <25Oct85>
BEQ.S @0 ; br if not <25Oct85>
MOVE.W TimeOutDrive(A1),D0 ; see if it's us <25Oct85>
CMP.W Drive(A1),D0 ; ? <25Oct85>
BEQ.S @0 ; br if so <25Oct85>
MOVEQ #0,D0 ; turn it off immediately <25Oct85>
JSR RPowerDown ; (it will still be selected) <25Oct85>
@0 CLR.W TimeOut(A1) ; clear pending timeout <11Jun85>
CMP.W #drive2,D1 ; if Drive=1 or 2, it's internal
BGT.S @1
CMP.W #drive1,D1 ;
BEQ.S @3 ; br if so
BCLR #vDriveSel,VBufD(A2) ; select internal drive 2
BRA.S @4 ; branch always
@3
BSET #vDriveSel,VBufD(A2) ; select drive 1
@4
TST.B IntDrive(A0) ; select internal drive
TST.B MtrOn(A0) ; assert /enb
RTS
@1
jmp RomAt1
ENDPROC
;____________________________________________________________________________________
; PA235 FClosePatch patch:
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 19Aug87 PP235 (FClose) (DtrmV3,
; FlushCache,
; BTClose,
; BTFlush)
;
; This patch fixes a problem in FClose which results in the catalog and extents file
; BTCBs not being released for an Unmount call. The branch following a test for a system
; CNID was reversed.
;
; Patched using the "DtrmV3", "FlushCache", "BTClose", and "BTFlush" vectors.
;
; The corresponding source code change for this patch were made to TFSRFN2.a in
; the "FClose" routine.
;
; 11Sep87 BB/JB Fixed FlushCache patch to save/restore async return address
; on a6 stack (PA269)
; 25Sep87 BB/JB Modified FlushCache patch (PA235) to check for an Offline, Eject,
; UnMountVol, or HUnMountVol trap before releasing the BTree
; control blocks (PA290).
; <54> dnf/csd Remove checks for _Offline and _Eject as we no longer close the
; catalog and extents files on these calls.
;____________________________________________________________________________________
FClosePatches proc
export saveDtrmV3,DtrmV3Patch,svFlushCache,FlCachePatch,BTClosePatch,BTFlushPatch
svFlushCache dc.l 0 ; Save of real FlushCache's address from vector
saveDtrmV3 dc.l 0 ; Save of real DtrmV3's address from vector
CatBTCBPtr dc.l 0 ; BTCB addr for catalog file
ExtBTCBPtr dc.l 0 ; BTCB addr for extent file
DtrmV3Patch
;
; Fake a JSR to the real DtrmV3 routine
;
pea @0 ; Where the real DtrmV3 will return to
move.l saveDtrmV3,-(sp) ; Go to it for now...
rts
@0
beq.s @1 ; Any errors from DtrmV3?
rts ; Return them to our caller if so...
@1
movem.l a0/a1/d1,-(sp)
cmp.w #TSigWord,VCBSigWord(a2) ; HFS volume?
bne.s @3 ; No, must be MFS so exit...
tst.w vcbFSID(a2) ; External file system (AppleShare)?
bne.s @3 ; Yep--get out of here...
;
; See if we came from Unmount
;
move.w ioTrap(a0),d0 ; Get trap we were called from
bclr #HFSBit,d0 ; (For unconditional UnMount) <25Sep87>
cmp.w #$A00E,d0 ; Unmount trap?
bne.s @3 ; Exit if not...
;
; For calls coming from Unmount, we have to save the catalog and
; extent file BTCB addresses so they can be deallocated later at FlushCache time.
;
@2
move.l FCBsPtr,a1 ; FCB array base address
move.w vcbCTRef(a2),d1 ; Catalog file refnum from VCB
beq.s @3 ; Exit if invalid catalog file refnum...
move.l fcbBTCBPtr(a1,d1),d0 ; Get BTCB pointer from FCB
lea CatBTCBPtr,a0 ; ...and save it for later
move.l d0,(a0)
move.w vcbXTRef(a2),d1 ; Extent file refnum from VCB
beq.s @3 ; Exit if invalid extent file refnum...
move.l fcbBTCBPtr(a1,d1),d0 ; Get BTCB pointer from FCB
lea ExtBTCBPtr,a0 ; ...and save it for later
move.l d0,(a0)
@3
movem.l (sp)+,a0/a1/d1
moveq #0,d0 ; Pseudo completion code
rts
;____________________________________________________________________________________
;
; FlushCache patch deallocates orphaned BTCBs uncovered by the DtrmV3 patch above.
; Patch looks for a call from inside FlushBuffers to make sure the BTCBs are
; released after the catalog and extent files have been flushed and closed.
;
;____________________________________________________________________________________
fromFlBufs equ $404F38 ; 1st return from FlushCache in FlushBuffers in SE ROM
FlCachePatch
move.l (sp)+,-(a6) ; Save async return address <11Sep87>
pea @0 ; Where the real FlushCache will return...
move.l svFlushCache,-(sp) ; Fake a JSR to the real FlushCache
rts
@0
movem.l d0/a0/a1,-(sp) ; Save FlushCache's return code & some regs
cmp.l #fromFlBufs,(a6) ; Coming from FlushBuffers? <11Sep87>
bne.s @5 ; Exit if not...
;
; See if we came from Unmount
;
move.l FSQHead,a0 ; Get ptr to current operation <25Sep87>
move.w ioTrap(a0),d0 ; Get trap we were called from <25Sep87>
bclr #HFSBit,d0 ; (For unconditional UnMount) <25Sep87>
cmp.w #$a00e,d0 ; Unmount trap? <25Sep87>
bne.s @5 ; Exit if not... <25Sep87>
@1
lea CatBTCBPtr,a1 ; Get saved catalog file BTCB address
move.l (a1),d0
beq.s @2 ; Skip if not defined...
move.l d0,a0 ; Else, point to it
_DisposePtr ; Deallocate orphan BTCB
clr.l (a1) ; ...and zap its reference
@2
lea ExtBTCBPtr,a1 ; Get saved extent file BTCB address
move.l (a1),d0
beq.s @5 ; Skip if not defined...
move.l d0,a0 ; Else, point to it
_DisposePtr ; Deallocate orphan BTCB
clr.l (a1) ; ...and zap its reference
@5
movem.l (sp)+,d0/a0/a1 ; Restore return code and registers
move.l (a6)+,-(a7) ; Restore async return address <11Sep87>
tst.w d0 ; Strobe FlushCache's return code
rts
;____________________________________________________________________________________
;
; BTClose patch to avoid BTClosing non-system BTree files
;
;____________________________________________________________________________________
vBTClose equ $4081AC
BTClosePatch
move.l a1,-(sp)
move.l FCBsPtr,a1
cmp.l #FSUsrCNID,FCBFlNm(a1,d0) ; Is this a 'system file'?
move.l (sp)+,a1
blo.s @1 ; If so, really flush it...
moveq #0,d0 ; Else, do nothing and return SUCCESS...
rts
@1
jmp vBTClose
;____________________________________________________________________________________
;
; BTFlush patch to avoid BTFlushing non-system BTree files
;
;____________________________________________________________________________________
vBTFlush equ $40839E
BTFlushPatch
move.l a1,-(sp)
move.l FCBsPtr,a1
cmp.l #FSUsrCNID,FCBFlNm(a1,d0) ; Is this a 'system file'?
move.l (sp)+,a1
blo.s @1 ; If so, really flush it...
moveq #0,d0 ; Else, do nothing and return SUCCESS...
rts
@1
jmp vBTFlush
endproc ; *** End of FClose patches ***
;____________________________________________________________________________________
; PA244 Unmount patch:
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 24Aug87 PA244 (Unmount) (Unmount)
;
; This patch prevents a volume from being unmounted if there are any open files
; on the requested volume. Side effects from letting this happen was typically
; a trashed catalog or extent file due to re-assignment of an FCB (refnum).
; In the MultiFinder environment, one application could unmount a volume out
; from underneath another.
;
; Patched using the "UnmountVol" trap.
;
; PMAB271 14Sep87 BB/JB Modified unmount patch PA244 to unconditionally unmount a
; volume if the HFS bit is set in the ioTrap word.
;____________________________________________________________________________________
UnmountPatch proc
RomFSQSync equ $4042e8 ; Mac SE FS queue sync
toUnmount equ $40508c ; Mac SE return from DtrmV3 in UnmountVol
jsr RomFSQSync ; Get in sync...
clr.b FlushOnly ; Setup same as UnmountVol
pea @1
move.l jDtrmV3,-(sp) ; Call DtrmV3 to do setup stuff
rts
@1 bne.s UnmountExit
;
; On return from DtrmV3, A2 contains the VCB ptr of the volume
; in question. Search the FCB array for open files that reference
; the volume...
;
moveq #0,d0 ; Initialize result code
btst #HFSBit,ioTrap(a0) ; Unconditional unmount? <14Sep87>
bne.s @6 ; Xfer if so... <14Sep87>
movem.l a1/d1/d2,-(sp)
move.l FCBsPtr,a1 ; FCB array base address
moveq #2,d1 ; Index of 1st FCB
@2
move.l fcbFlNm(a1,d1),d2 ; Is the file currently open?
beq.s @4 ; Nope, try next FCB...
cmp.l fcbVPtr(a1,d1),a2 ; Is the file on the vol in question?
bne.s @4 ; No, try next FCB...
cmp.w #Tsigword,vcbSigWord(a2) ; is sigword that of TFS?
bne.s @3 ; Yes, assert UnmountVol error
cmp.l #FSUsrCNID,d2 ; is it an internal file?
blo.s @4 ; if so, try next FCB...
cmp.l #$47525420,d2 ; is it a fake AppleShare FCB?
beq.s @4 ; yes, skip it...
@3 moveq #fBsyErr,d0 ; assert UnmountVol error
bra.s @5 ; Get out...
@4
add.w FSFCBLen,d1 ; Next FCB array entry
cmp.w (a1),d1 ; Reached the end yet?
blo.s @2 ; Continue search...
@5
movem.l (sp)+,a1/d1/d2
@6 ; <14Sep87>
tst.w d0 ; Were files open?
UnmountExit:
jmp toUnmount
endproc ; *** End of Unmount patch ***
;____________________________________________________________________________________
; PMAB241 BadTrap Handler patch
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchIIROM.a 25Aug87 PMAB241 (BadTrap) (BadTrap)
;
; This patch is to salvage D0 reg for MacsBug on Debugger traps which use the ROM BadTrap routine.
; Fix is to save regs prior to using D0 reg for error code.
;____________________________________________________________________________________
NewBadTrap PROC EXPORT
ROMSysErr3 EQU $40138E ; ROM entry point in SysErr after save of regs
MOVEM.L D0-D7/A0-A7,SEVars ; save all regs for debugger
MOVEQ #12,D0 ; signal bad trap error
JMP ROMSyserr3 ; and go to ROM, don't resave regs
ENDPROC
IF (NOT hasSplineFonts) THEN ;<2.3-4april89-CEL>
;____________________________________________________________________________________
; PMA299 27Oct87 NMB StdTxMeas DrText
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 27Oct87 #PMA299 (StdTxMeas) (DrText)
;
; This patch fixes QuickDraw so that it properly handles fonts in excess of 128Kb. This is done
; by checking the FNDESCENT field of the FontRec. If that value is positive, then that word is
; used as the upper 16 bits of the offset/width table pointer.
NewStdTxMeas PROC EXPORT
seDrTextAddr EQU $4136D6 ; Address of code after call from DrText in SE Rom
seSTMAddr EQU $413486 ; Beginning of StdTxMeas in SE ROM
seBack2DrText EQU $413954 ; ROM address to continue execution
CMPI.L #seDrTextAddr,(SP) ; Being called from DrText? *NB Patch*
BEQ.S seChgRtn ; Yes, change Return Address. *NB Patch*
JMP seSTMAddr ;Otherwise, jump to ROM (beginning of StdTxMeas) *NB Patch*
seChgRtn ADDQ.L #4,SP ;Pop the old return address offÉ
PEA seDrTextPatch ;Replace return address with patch code *NB Patch*
JMP seSTMAddr ;Now, jump to ROM (beginning of StdTxMeas) *NB Patch*
;____________________________________________________________________________________
; PMA299 27Oct87 NMB DrText DrText
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 27Oct87 #PMA299 (DrText) (DrText)
;
; This patch completes the fix to QuickDraw so that it properly handles fonts in excess of 128Kb.
; This is done by checking the FNDESCENT field of the FontRec. If that value is positive,
; then that word is used as the upper 16 bits of the offset/width table pointer. However, the
; first code executed tests to see if the FNDESCENT is truly positive. If it is not, then the
; ROM version of DrText is executed instead.
SEfNDescent EQU 10 ;Word: *NB Patch*
SEMapRectROM EQU $418D58 ;ROM Address of MapRect *NB Patch*
SEGoHomeROM EQU $413DC6 ;ROM Address of GoHome in DrText *NB Patch*
SERSectROM EQU $414880 ;ROM Address of RSect *NB Patch*
SETrimRectROM EQU $41692A ;ROM Address of TrimRect *NB Patch*
SEShieldCursorROM EQU $412A34 ;ROM Address of ShieldCursor *NB Patch*
SEDrTextROM EQU $413696 ;ROM Address of DrText *NB Patch*
;-------------------------------------------
;
; KERNED STRIKE FONT FORMAT OFFSETS:
;
FORMAT EQU 0 ;WORD
MINCHAR EQU 2 ;WORD
MAXCHAR EQU 4 ;WORD
MAXWD EQU 6 ;WORD
FBBOX EQU 8 ;WORD
FBBOY EQU 10 ;WORD
FBBDX EQU 12 ;WORD
FBBDY EQU 14 ;WORD
LENGTH EQU 16 ;WORD
xfASCENT EQU 18 ;WORD
XOFFSET EQU 22 ;WORD
RASTER EQU 24 ;WORD
;------------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE EQU 14 ;SIZE OF PARAMETERS
COUNT EQU PARAMSIZE+8-2 ;WORD
TEXTADDR EQU COUNT-4 ;LONG
NUMER EQU TEXTADDR-4 ;LONG, POINT
DENOM EQU NUMER-4 ;LONG, POINT
;-----------------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
SAVESTK EQU -4 ;LONG
TEXTRECT EQU SAVESTK-8 ;RECT
TEXTR2 EQU TEXTRECT-8 ;RECT
MINRECT EQU TEXTR2-8 ;RECT
BUFEND EQU MINRECT-4 ;LONG
BUFSTART EQU BUFEND-4 ;LONG
BUFFSIZE EQU BUFSTART-2 ;WORD
BUFROW EQU BUFFSIZE-2 ;WORD
BUFLEFT EQU BUFROW-2 ;WORD
BUF2START EQU BUFLEFT-4 ;LONG
BUF2END EQU BUF2START-4 ;LONG
HEIGHT EQU BUF2END-2 ;WORD
SRCBITS EQU HEIGHT-14 ;BITMAP
DSTBITS EQU SRCBITS-14 ;BITMAP
FAKERGN EQU DSTBITS-10 ;RECTANGULAR REGION
FAKEPTR EQU FAKERGN-4 ;LONG, FAKE MASTER POINTER
SRCADDR EQU FAKEPTR-4 ;LONG
SRCROW EQU SRCADDR-2 ;WORD
FASTFLAG EQU SRCROW-2 ;BYTE
PENLOC EQU FASTFLAG-4 ;POINT
SRCPTR EQU PENLOC-4 ;LONG
DSTPTR EQU SRCPTR-4 ;LONG
STRETCH EQU DSTPTR-2 ;BOOLEAN
FROMRECT EQU STRETCH-8 ;RECT
TORECT EQU FROMRECT-8 ;RECT
SRCRECT EQU TORECT-8 ;RECT
DSTRECT EQU SRCRECT-8 ;RECT
SPWIDTH EQU DSTRECT-4 ;FIXED POINT
CHARLOC EQU SPWIDTH-4 ;FIXED POINT
INFO EQU CHARLOC-8 ;4 WORDS
HEIGHTAB EQU INFO-4 ;LONG
WIDTAB EQU HEIGHTAB-4 ;LONG
LOCTAB EQU WIDTAB-4 ;LONG
TOPHT EQU LOCTAB-2 ;word
HEIGHTFLAG EQU TOPHT-2 ;byte
MAXMIN EQU HEIGHTFLAG-2 ;word
MINCH EQU MAXMIN-2 ;word
SAVEA5 EQU MINCH-4 ;LONG
NUMER2 EQU SAVEA5-4 ;Point
DENOM2 EQU NUMER2-4 ;Point
VARSIZE EQU DENOM2 ;SIZE OF VARIABLES
; *NB Patch* We enter patch land immediately after a jump to StdTxMeas. That routine knows
; that if it is called from DrText that it should jump to the patch rather than return.
seDrTextPatch MOVE.L $99A,A2 ; Get handle to FontRecord
MOVE.L (A2),A2 ; Dereference
TST.W sefNDescent(A2) ; Is fNDescent>0?
BGT.S seDoDrTextPatch ; Yup, execute patch code
JMP seDrTextAddr ; Jump back to ROM.
seDoDrTextPatch MOVE (SP)+,D1 ;POP UNSCALED WIDTH RESULT
;
; StdTxMeas also stashes FMOutPtr in QD global FONTPTR,
; and unscaled fixed point text width in FixTxWid.
;
MOVE.L FONTPTR(A4),A4 ;POINT TO FMOUTPUT
MOVE.L 2(A4),A2 ;GET FONT HANDLE
MOVE.L (A2),A2 ;DE-REFERENCE IT
MOVE FBBDY(A2),TOPHT(A6) ;INIT TOPHT IN CASE OLD FONT
BTST #0,1(A2) ;DOES FONT HAVE HEIGHT TABLE ?
SNE HEIGHTFLAG(A6) ;REMEMBER FOR LATER
;
; Setup textRect, the rectangle bounding the entire string.
;
MOVE.L PNLOC(A3),D2 ;GET PEN LOCATION
MOVE.L D2,PENLOC(A6) ;SAVE FOR LATER
MOVE.W D2,TEXTRECT+LEFT(A6) ;TEXTRECT.LEFT := PNLOC.H
ADD.W D1,D2 ;right := left + width
MOVEQ #7,D0 ;get mode mask
AND TXMODE(A3),D0 ;is txMode = srcCopy ?
BEQ.S seNOSLOP ;yes, don't add slop
CMP #3,D0 ;is textMode > srcBic ?
BGT.S seNOSLOP ;yes, don't add slop
ADD.W #32,D2 ;SLOP FOR ITALIC,BOLD,OVERSTRIKE
seNOSLOP MOVE.W D2,TEXTRECT+RIGHT(A6) ;STORE IN TEXTRECT.RIGHT
SWAP D2 ;GET PNLOC.V
SUB xfASCENT(A2),D2 ;SUBTRACT ASCENT
MOVE D2,TEXTRECT+TOP(A6) ;TEXTRECT.TOP := PNLOC.V - ASCENT
ADD FBBDY(A2),D2 ;ADD HEIGHT
MOVE D2,TEXTRECT+BOTTOM(A6) ;TEXTRECT.BOTTOM := TOP + HEIGHT
MOVE.L TEXTRECT(A6),TEXTR2(A6) ;MAKE AN EXTRA COPY
MOVE.L TEXTRECT+4(A6),TEXTR2+4(A6) ;OF TEXTRECT IN TEXTR2
;
; Check for stretching
;
MOVE.L NUMER(A6),D0 ;GET NUMERATOR
CMP.L DENOM(A6),D0 ;ARE WE STRETCHING ?
SNE STRETCH(A6) ;REMEMBER THE ANSWER
BEQ.S seNOSTRCH ;CONTINUE IF NOT STRETCHING
;
; We will be stretching. Setup fromRect and toRect and map textR2.
;
MULU D0,D1 ;MULT WIDTH BY NUMER.H
DIVU DENOM+H(A6),D1 ;DIV BY DENOM.H
MOVE.L PENLOC(A6),D0 ;GET PENLOC
MOVE.L D0,TORECT+TOPLEFT(A6) ;SET UP TORECT TOPLEFT
ADD.W NUMER+H(A6),D0 ;CALC PENLOC.H + NUMER.H
MOVE D0,TORECT+RIGHT(A6) ;SET UP TORECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD NUMER+V(A6),D0 ;CALC PENLOC.V + NUMER.V
MOVE D0,TORECT+BOTTOM(A6) ;SET UP TORECT BOTTOM
MOVE.L PENLOC(A6),D0 ;GET PENLOC
MOVE.L D0,FROMRECT+TOPLEFT(A6) ;SET UP FROMRECT TOPLEFT
ADD.W DENOM+H(A6),D0 ;CALC PENLOC.H + DENOM.H
MOVE D0,FROMRECT+RIGHT(A6) ;SET UP FROMRECT RIGHT
SWAP D0 ;GET PENLOC.V
ADD DENOM+V(A6),D0 ;CALC PENLOC.V + DENOM.V
MOVE D0,FROMRECT+BOTTOM(A6) ;SET UP FROMRECT BOTTOM
PEA TEXTR2(A6) ;PUSH TEXTR2
PEA FROMRECT(A6) ;PUSH FROMRECT
PEA TORECT(A6) ;PUSH TORECT
JSR seMapRectROM ; MAP TEXTR2 (PRESERVES ALL REGS) (MapRect) *NB Patch*
seNOSTRCH ADD D1,PNLOC+H(A3) ;BUMP PEN BY (SCALED) TEXT WIDTH
;
; Quit if the pen is hidden
;
TST PNVIS(A3) ;IS PNVIS < 0 ?
BLT seGoHome ;YES, QUIT *NB Patch*
;
; Calc minRect: the intersection of textRect, bitMap bounds,
; clipRgn and visRgn bounding boxes. Quit if no intersection.
;
PEA TEXTR2(A6) ;PUSH (MAPPED) TEXTRECT
PEA PORTBOUNDS(A3) ;PUSH BITMAP BOUNDS
MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH CLIPRGN BBOX
MOVE.L VISRGN(A3),A0 ;GET VISRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH VISRGN BBOX
MOVE #4,-(SP) ;PUSH NRECTS=4
PEA MINRECT(A6) ;PUSH DST ADDR
JSR seRSectROM ;CALC INTERSECTION (RSect) *NB Patch*
BEQ seGoHome ;QUIT IF NO INTERSECTION *NB Patch*
;
; Set up srcAddr, srcRow, and height
;
LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVE.L A0,SRCADDR(A6) ;SAVE FOR LATER
MOVE RASTER(A2),D1 ;GET WORDS PER ROW IN FONT
ADD D1,D1 ;DOUBLE FOR BYTES PER ROW
MOVE D1,SRCROW(A6) ;REMEMBER FOR LATER
MOVE FBBDY(A2),HEIGHT(A6) ;SETUP HEIGHT FOR LATER
;
; Test for fast case:
; not stretched, no color mapping, txMode = srcOr,
; not bold, italic, underlined, outlined or shadowed,
; visRgn and clipRgn both rectangular.
;
TST.W 6(A4) ;TEST BOLD AND ITALIC
BNE seNOTFAST ;NOT FAST UNLESS BOTH ZERO
CMP #1,TXMODE(A3) ;IS TEXT MODE SRCOR ?
BNE seNOTFAST ;NO, NOT FAST
TST.W 10(A4) ;TEST ULTHICK AND SHADOW
BNE seNOTFAST ;NOT FAST UNLESS BOTH ZERO
TST.B STRETCH(A6) ;IS TEXT STRETCHED ?
BNE seNOTFAST ;YES, NOT FAST
MOVE COLRBIT(A3),D1 ;ARE WE COLOR MAPPING ?
BMI.S seNOCOLOR ;NO, CONTINUE
MOVE.L BKCOLOR(A3),D0 ;YES GET BACKGROUND COLOR
NOT.L D0 ;INVERT IT
AND.L FGCOLOR(A3),D0 ;AND WITH FOREGROUND COLOR
BTST D1,D0 ;IS THAT PLANE NORMAL ?
BEQ seNOTFAST ;NO, NOT FAST
seNOCOLOR MOVE.L CLIPRGN(A3),A0 ;GET CLIPRGN HANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
MOVEQ #10,D0
CMP RGNSIZE(A0),D0 ;IS CLIPRGN RECTANGULAR ?
BNE.S seNOTFAST ;NO, NOT FAST
MOVE.L VISRGN(A3),A1 ;GET VISRGN HANDLE
MOVE.L (A1),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D0 ;IS VISRGN RECTANGULAR ?
BEQ.S seFAST ;YES, TAKE FAST OPTIMIZATION
;
; All systems go except for VisRgn not rectangular.
; Check if visRgn sect minRect is rectangular.
; IF TrimRect(visRgn,minRect) THEN take the fast way.
;
MOVE.L A1,-(SP) ;PUSH VISRGN
PEA MINRECT(A6) ;PUSH MINRECT
JSR seTrimRectROM ;Call TrimRect *NB Patch*
BLT seGoHome ;quit if intersection empty *NB Patch*
BGT.S seNOTFAST ;continue if non-rectangular
;
; Fast case, go directly to screen.
; If text is clipped vertically, then clear heightflag and update TOPHT
;
seFAST ST FASTFLAG(A6) ;REMEMBER WE'RE GOING FAST
MOVE MINRECT+TOP(A6),D0 ;GET MINRECT.TOP
MOVE MINRECT+BOTTOM(A6),D1 ;GET MINRECT.BOTTOM
SUB TEXTRECT+TOP(A6),D0 ;was top clipped ?
BNE.S seVCLIP ;yes, handle clip
CMP TEXTRECT+BOTTOM(A6),D1 ;was bottom clipped ?
BEQ.S seVCLIPOK ;no, continue
seVCLIP CLR.B HEIGHTFLAG(A6) ;can't use height table
MOVE.B D0,TOPHT(A6) ;use adjusted top
SUB MINRECT+TOP(A6),D1 ;calc clipped height
MOVE.B D1,TOPHT+1(A6) ;replace TOPHT
seVCLIPOK MOVE TEXTRECT+TOP(A6),D0 ;GET DST TOP
SUB PORTBOUNDS+TOP(A3),D0 ;CONVERT TO GLOBAL COORDINATES
MULS PORTBITS+ROWBYTES(A3),D0 ;MULT BY ROWBYTES
ADD.L PORTBITS+BASEADDR(A3),D0 ;ADD START OF DST BITMAP
MOVE.L D0,BUFSTART(A6) ;SET UP BUFSTART FOR LATER
MOVE PORTBITS+ROWBYTES(A3),BUFROW(A6) ;SET UP BUFROW FOR LATER
MOVE PORTBOUNDS+LEFT(A3),BUFLEFT(A6) ;REMEMBER BUFLEFT
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L PORTBOUNDS+TOPLEFT(A3),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL
JSR seShieldCursorROM ;Hide Cursor if it intersects *NB Patch*
BRA seGETPTRS
;
; Slow case: Setup for an off-screen buffer.
;
; Calc bufLeft: (word-align to avoid shift)
;
seNOTFAST CLR.B FASTFLAG(A6) ;NOT GOING DIRECTLY TO SCREEN
MOVE TEXTRECT+LEFT(A6),D0 ;GET TEXTRECT LEFT
SUB PORTBOUNDS+LEFT(A3),D0 ;CONVERT TO GLOBAL
AND #$FFF0,D0 ;TRUNC TO WORD BOUND
SUB #32,D0 ;32 DOT SLOP FOR SLANT & SHADOW
ADD PORTBOUNDS+LEFT(A3),D0 ;RETURN TO LOCAL COORDS
MOVE D0,BUFLEFT(A6) ;REMEMBER FOR LATER
;
; Calculate buffer size
;
MOVE TEXTRECT+RIGHT(A6),D1 ;BUFRIGHT := TEXTRECT RIGHT
SUB D0,D1 ;WIDTH:=BUFRIGHT-BUFLEFT
LSR #5,D1 ;CONVERT DOTS TO LONGS
ADD #2,D1 ;ROUND UP PLUS EXTRA LONG
MOVE HEIGHT(A6),D3 ;GET HEIGHT
MULU D1,D3 ;BUFFSIZE:=HEIGHT*BUFROW LONGS
MOVE D3,BUFFSIZE(A6) ;SAVE FOR LATER
LSL #2,D1 ;QUAD BUFROW FOR BYTES
MOVE D1,BUFROW(A6) ;SAVE FOR LATER
;
; Calculate total stack requirements for off-screen buffers.
;
MOVE.L D3,D2 ;GET BUFFSIZE LONGS
TST.B 11(A4) ;ARE WE SHADOWING ?
BEQ.S @se1 ;NO, CONTINUE
ADD.L D2,D2 ;YES, CALC 2*BUFFSIZE
EXT.L D1 ;SIGN EXTEND BUFROW
ADD.L D1,D2 ;CALC TOTAL LONGS
@se1 LSL.L #2,D2 ;CALC TOTAL STACK BYTES NEEDED
ADD.L #1024,D2 ;ADD 1 KBYTE SLOP
;
; If stack is too small to allocate buffer(s), then recursively call
; DrText with the left half and the right half of the text string.
;
_StackAvail ;Get StackAvail IN D0 {StackSpace?}
CMP.L D0,D2 ;IS stackNeeded > stackAvail ?
BLE.S seSTACKOK ;NO, CONTINUE
MOVE.L PENLOC(A6),PNLOC(A3) ;RESTORE PNLOC TO ORIGINAL
MOVE COUNT(A6),D7 ;GET CHARACTER COUNT
LSR #1,D7 ;DIVIDE IN HALF
BEQ.S seGoHome ;GIVE UP IF COUNT WAS ONLY ONE *NB Patch*
MOVE D7,-(SP) ;PUSH NEW COUNT
MOVE.L TEXTADDR(A6),-(SP) ;PUSH TEXTADDR
MOVE.L NUMER2(A6),-(SP) ;PUSH ORIGINAL NUMER
MOVE.L DENOM2(A6),-(SP) ;PUSH ORIGINAL DENOM
JSR seDrTextROM ;DRAW THE FIRST HALF *NB Patch*
MOVE COUNT(A6),D0 ;GET ORIGINAL CHARACTER COUNT
SUB D7,D0 ;SUBTRACT CHARS ALREADY DONE
MOVE D0,-(SP) ;PUSH NEW COUNT
MOVE.L TEXTADDR(A6),A0 ;GET ORIGINAL TEXTADDR
ADD D7,A0 ;BUMP PAST CHARS ALREADY DONE
MOVE.L A0,-(SP) ;PUSH NEW TEXTADDR
MOVE.L NUMER2(A6),-(SP) ;PUSH ORIGINAL NUMER
MOVE.L DENOM2(A6),-(SP) ;PUSH ORIGINAL DENOM
JSR seDrTextROM ;DRAW THE SECOND HALF *NB Patch*
; BRA seGoHomeROM ;AND QUIT ! *NB Patch*
seGoHome JMP seGoHomeROM ;Hack so that I can jump to ROM with a Bcc instr. *NB patch*
;
; Allocate and clear an off-screen buffer
;
seSTACKOK SUB #1,D3 ;INIT DBRA LOOP COUNT
CLR.L -(SP) ;PAD BUFFER WITH AN EXTRA ZERO
MOVE.L SP,BUFEND(A6) ;REMEMBER WHERE BUFFER ENDS
seCLRLOOP CLR.L -(SP)
DBRA D3,seCLRLOOP ;ALLOCATE AND CLEAR BUFFER
MOVE.L SP,BUFSTART(A6) ;REMEMBER START OF BUFFER
CLR.L -(SP) ;PAD BUFFER WITH AN EXTRA ZERO
;
; Get pointers to location table, width table, and height table in font
;
seGETPTRS LEA 26(A2),A0 ;GET START OF FONT BITMAP
MOVE FBBDY(A2),D0 ;GET HEIGHT OF FONT BITMAP
MULU SRCROW(A6),D0 ;CALC TOTAL SIZE OF STRIKE
ADD.L D0,A0 ;A1 := START OF LOC TABLE
MOVE.L A0,LOCTAB(A6) ;SAVE FOR LATER
;*NB Patch* The code for DrText must be able to handle fonts >128K. In order to do this, the font has
; the fNDescent field > 0. We use whatever value fNDescent has (if >0) as the upper 16 bits of the
; 32 bit distance to the offset/width table. We normally just use LENGTH(A2), and clear the upper
; 16 bits, but here we use fNDescent as the upper 16 bits, giving us greater range.
MOVE.W sefNDescent(A2),D0 ;Examining for >128K fonts *NB Patch*
BPL.S seMore128K ;If fNescent>0, then font > 128K. *NB Patch*
CLR.W D0 ;If not pos, then clear out fNDescent and continue. *NB Patch**
seMore128K SWAP D0 ;Put fNDescent into upper word to augment LENGTH(A2) *NB Patch*
JMP seBack2DrText
ENDIF ;<2.3-4april89-CEL>
;____________________________________________________________________________________
; PMAB301 ATP delayed duplicate response bug patch
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 16Nov87 PMAB301 SendRequest SendRequest
;
; If a delayed duplicate response came in to ATP it could overwrite a valid response
; before it was thrown out due to a bad TID. Patch SendRequest to install a new socket
; listener which checks the TID first. Patch installed in the ATP control hook.
;____________________________________________________________________________________
ATPPatch PROC EXPORT
ROMJATPEx2 EQU $4328DC
ROMSndRqInit EQU $4329B8
ToROMSendReq EQU $4328FC
ROMATPIgnore EQU $432DF2
ROMReadResp EQU $432E06
TCBE EQU 12 ; Number of TCB's
TSktNum EQU 4 ; Offset to socket no.
TQElPtr EQU TSktNum+TCBE ; Offset to qEl ptr
CMP #SendRequest,CSCode(A0) ; Is it SendRequest?
BNE.S AnRTS ; Just return if not
MOVE.L MaskBC,D3 ; D3 = mask value
AND.L (SP),D3 ; Mask calling address
CMP.L ROMBase,D3 ; Make sure called from ROM
BLO.S AnRTS ; Just return if not
ADDQ #4,SP ; Pop return address
MOVE.L AbusVars,A2 ; A2 -> MPP variables
MOVE.L ATPVars(A2),A2 ; A2 -> ATP variables
MOVE.L AddrBlock(A0),D3 ; D3 = address block from queue element
AND.B #FlagMask,ATPFlags(A0) ; Make sure nothing but flag bits
MOVE #TooManyReqs,D0 ; Assume too many concurrent requests
MOVEQ #TCBE-1,D2 ; D2 = offset into TCB table
@10 TST.B TSktNum(A2,D2) ; Is this entry free?
DBEQ D2,@10 ; Keep going until got one
BNE.S @20 ; Return error if none
JSR ROMSndRqInit ; Do initial setup. A3 -> data area.
BNE.S @20 ; Just return if error
CLR.B D1 ; Indicate we want a dynamic socket
LEA newATPRead,A1 ; A1 -> new socket listener
JMP ToROMSendReq ; Jump into ROM
@20 JMP ROMJATPEx2
AnRTS RTS ; Just return if not SendRequest
;
; This is the real patch. We make sure the TID matches before reading in
; the response
;
newATPRead MOVEQ #ATPHdSz,D3 ; D3 = size to read
CMP.B #ATP,-(A3) ; Make sure DDP type was ATP (46)
BNE.S @20 ; Ignore it if not, (RHA ptr now even)
JSR (A4) ; Read header into RHA
BNE.S AnRTS ; Just return if error
MOVE.L ATPVars(A2),A5 ; A5 -> our local variables
MOVE.B DDPDstSkt-DDPType-ATPHdSz(A3),D0 ; D0 = dest. socket no.
MOVE.B ATPControl-ATPHdSz(A3),D2 ; D2 = control byte
BPL.S @20 ; Ignore if not a response (2)
ADD.B D2,D2 ; Shift it left one bit
BMI.S @20 ; Ignore if not a response (3)
;
; Incoming response - find the TCB for it and read it in
;
MOVEQ #TCBE-1,D2 ; D2 = number to search, less one
LEA TSktNum+TCBE(A5),A5 ; A5 -> past sockets
@10 CMP.B -(A5),D0 ; This it? (fast loop!)
DBEQ D2,@10 ; Try all we can
BNE.S @20 ; Ignore it if no match
SUB D2,A5 ; A5 -> start of TCB table
LSL #2,D2 ; D2 = offset to queue element pointer
ADD D2,A5 ; A5 -> queue element ptr, offset
MOVE.L TQElPtr-TSktNum(A5),A5 ; A5 -> queue element
;
; *** The actual fix ***
;
MOVE ATPTransID-ATPHdSz(A3),D0 ; D0 = TID from packet
CMP ReqTID(A5),D0 ; Is it the one we want?
BNE.S @20 ; If not just ignore it
JMP ROMReadResp ; Otherwise continue
@20 JMP ROMATPIgnore ; Ignore the packet
;____________________________________________________________________________________
; PMAB372 Async serial driver patch
;
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
;AppleSystemPatch PatchSEROM.a 26jan88 PMAB372 (AOutOpen,RAIntHnd) (RAIntHnd)
;AppleSystemPatch PatchSEROM.a 23Feb88 PMAB401 (Control) (Control)
;
; If hardware handshaking is enabled, and the receiver de-asserts DTR, but the sender ignores
; it and keeps sending, the receiver will go into an infinite loop in the receive interrupt
; routine. This was caused by a jump to the wrong label. The patch is installed in a patch
; vector for the async driver. Needed to include all async driver code which jumped to
; the receive interrupt handler.
;
; In Control, if the patch was called from control, then clear reg D0 before returning. This
; fixes a bug where killIO returns without setting reg D0 to good status.
;
;
;AppleSystemPatch PatchIIROM.a 17Dec90 <51> (all driver entry points,InitSCC,all int handlers)
; We need to add provide nike printer support. This entails:
; -- patch control call 16 to use bit 6 for setting external/internal clocking modes.
; -- Patch to add status call to return version.
; -- Patch InitSCC routine to use this RAM-based table so
; that clocking mode is now variable instead of hard-wired to internal only.
; -- set clock divide to 1 instead of 16 for external clocking
; -- clear HWHS enable since we can't clock and handshake on same line
; -- Patch whole ExtIntHandler so we can (set bit 3 of AsyncErr if break rcvd) at end of rtn.
; Also, we change the BAP stuff such that it is also supported in 6.x, not just 7.0
; -- Always get the driver storage pointer for port B from extended mem
; -- Call Gestalt in Open and Close to determine version of AppleTalk to see which
; port arbitration scheme we should use, ours or the LAP mgr's.
;
;AppleSystemPatch PatchIIROM.a 16Jan91 <52> (all A driver entry points)
; We patch all the port A driver headers (port B driver headers already patched)
; so that we can put a signature word before each header that we can use
; to identify ourselves as the Apple async serial driver. We do this
; right now so that that our linked patch on Open (in Serialpatches.a) will
; not stomp the version number of some third party driver that sticks them-
; selves into our spot in the unit table. I think this idea will come in
; handy later as well.
; I think i'll use the signature word 'wong'.
; Also, fix the port arbitration code in Open and Close to make call to the
; new 'atkv' Gestalt call instead of the old 'atlk' call. We do this because
; the new call return atalk version number regardless of whether MPP driver
; is open (i.e. appletalk is active).
;
; <55> Fixed bug in external clock stuff that was causing us to disable
; internal clocking on both ports if we were trying to do external
; clocking on just one. So Nike would print but Tabasco would just
; sit there. The fix was to set clocking params at each time we go
; thru InitSCC, rather than just once during the external clocking
; control call. This way even tho the ports share the InitSCCTable,
; we set the Table properly by keying off of the value in CtlOptions
; variable, which they don't share.
; <57> Status calls 9 and $8000 now return static version number instead
; of what's in the DCE.
asyncPatch PROC EXPORT
; Async serial driver equates
SerialVers equ 5 ; current version 3/91 <57>
SCCARWOFF equ 2 ; SCC A side R/W offset
SCCBRWOFF equ 0 ; SCC B side R/W offset
PortAVars EQU SerialVars ; serial chan A variables and buffer
AInDCE EQU PortAVars+4 ; Device Control Entry ptr for input
PortBVars EQU AInDCE+4 ; serial port B variables and buffer
BInDCE EQU PortBVars+4 ; Device Control Entry ptr for input
; next come variable offsets within the user's local variable buffer
OutDCE EQU 0 ;(4) long DCE pointer for output driver
SCCOffset EQU 4 ;(2) word of SCC offset . . .
InBufPtr EQU 6 ;(4) pointer to local input buffer
;BufSize EQU 10 ;(2) size of local input buffer
BufLow EQU 12 ;(2) low buf byte count to send XOn
BufHigh EQU 14 ;(2) bytes from end of buffer to send XOff
SWHS EQU 16 ;(1) software handshake enable
HWHS EQU 17 ;(1) hardware handshake enable
XONChar EQU 18 ;(1) input char which continues output (SWHS)
XOFFChar EQU 19 ;(1) input char which stops output
Options EQU 20 ;(1) bit 4 = abort on parity error
; bit 5 = abort on overrun
; bit 6 = abort on framing error
PostOptions EQU 21 ;(1) bit 7=1 enables posting break changes
; bit 5=1 enables posting handshake changes
InSWHS EQU 22 ;(1) input XOn/XOff flow control enable
InHWHS EQU 23 ;(1) input RTS (DTR) flow ctl enb <14Oct85>
AsyncErr EQU 24 ;(1) error indications (cumulative)
SoftOR EQU 0 ; bit 0 = soft overrun
; bit 4 = parity error
; bit 5 = overrun error
; bit 6 = framing error
FlowOff EQU 25 ;(1) $80 = input flow shut off by XOff, $40 by DTR
ReadCmd EQU 26 ;(1) FF = read command pending
WriteCmd EQU 27 ;(1) FF = write command pending
CTSFlag EQU 28 ;(1) FF = CTS asserted
XOFFlag EQU 29 ;(1) FF = XOFF pending
LastWR5 EQU 30 ;(1) WR5 value with last DTR state
DTRNegVal EQU 31 ;(1) WR5 value used to negate DTR
SCCReset EQU 32 ;(1) WR9 value for reset
StopBits EQU 33 ;(1) stop bits/parity option (WR4 value)
WR1AVal EQU 34 ;(1) first WR1 value to write
WR3AVal EQU 35 ;(1) first WR3 value to write
WR5AVal EQU 36 ;(1) first WR5 value to write
BaudLoCnst EQU 37 ;(2) 2 byte baud rate constant (WR12-13)
BaudHiCnst EQU 38
RcvrBits EQU 39 ;(1) 1 byte receiver bits/char (WR3 value)
XmitBits EQU 40 ;(1) 1 byte xmitter bits/char (WR5 value)
WReqPin EQU 41 ;(1) w/req pin state (WR1 value)
lastSetup EQU 42 ;(2) last SCC init values . . .
BufIndex EQU 44 ;(2) index into local buffer (insert)
BufOutdex EQU 46 ;(2) index into local buffer (remove)
LocalBuf EQU 48 ;(64) local buffer for input chars
LclBufSize EQU 64 ; default input buffer size = 64 bytes
HSCount EQU 112 ;(2) count of CTS pulses in VBL time (clk detect)
LastTime EQU 114 ;(4) ticks time of last CTS pulse (clk detect)
SendXOnff EQU 118 ;(1) flag to xmit logic to send XOn/XOff
CharMask EQU 119 ;(1) $1F,$3F,$7F, or $FF mask for input chars
PEChar EQU 120 ;(1) char to change incoming parity errors to
AltChar EQU 121 ;(1) char to change incoming PEChars to
InSWHS1 EQU 122 ;(1) saved InSWHS state
CtlOptions EQU 123 ;(1) bits 0-6=0 (reserved). bit 7=1 to leave
; DTR state unchanged at close.
SaveExInt EQU 124 ;(4) saved Ext int vector
SaveTxInt EQU 128 ;(4) saved TxD int vector
SaveRxInt EQU 132 ;(4) saved RxD int vector
SaveSxInt EQU 136 ;(4) saved Special Rx int vector
LclVarSize EQU 140 ; output driver storage size
;come from addresses
fromAInOpen EQU $431c4a
fromAOutOpen EQU $431CAE
fromBOutOpen EQU $431CDC
fromBInOpen EQU $431c52
fromControl EQU $431F9A
fromStatus EQU $431f48
fromClose EQU $431ebc
fromInitSCC EQU $431e3a
; open call patch equates
backToAOutOpen EQU $431Cca
backToAInOpen EQU $431c4a
backToBOutOpen EQU $431Cf6
backToBInOpen EQU $431c56
ROM_TAIntHnd EQU $4321f4 ; interrupt handlers we're NOT patching
backToPollDtain EQU $432314 ;
ToContOut EQU $432216 ;
ToGoodFinish EQU $4321B0 ;
ToGetBufRegs EQU $43228E ;
ToGetBufCnt EQU $43229E ;
ToCtlXOff EQU $4323BC ;
ToPut EQU $4323B6 ;
backToPut EQU $4323B2 ;
ToRdReqDone EQU $432422 ;
ToCtlSet EQU $4320cc
toContOut1 EQU $43221a
; Control Patch equates
backToBypassControl EQU $431fac
ROM_CtlGood EQU $431fe2
ROM_CtlExit EQU $431fe4
; Control Call 16 patch equates
InitSCC EQU $431e2a
;
; Status patch equates
backToStatus EQU $431f62
;InitSCC patch equates
backToInitSCC EQU $431e3a
initData EQU $431df6
; Close patch equates
SyncOutput EQU $431f0e
InitSCC1 EQU $431e30
ResetData EQU $431e80
ResetLth EQU $10
freePort EQU $431efc
; bypass driver ROM entrypoint addresses <52>
;port A
ROM_AInEntryOpen EQU $431c48
ROM_AInEntryClose EQU $431f0a
ROM_AInEntryPrime EQU $432226
ROM_AOutEntryOpen EQU $431cac
ROM_AOutEntryClose EQU $431e90
ROM_AOutEntryPrime EQU $43216c
ROM_AEntryControl EQU $431f86
ROM_AEntryStatus EQU $431f34
;port B
backToBInOpenStart EQU $431c50
backToBOutOpenStart EQU $431cda
ToBOutClose EQU $431ea4
backToBInPrime EQU $432230
backToBOutPrime EQU $432176
backToBControl EQU $431f90
backToBStatus EQU $431f3e
; for BAP only interrupt handler patches
backToTXIntHnd EQU $4321f8
; for BAP only patches-- since these are not in Interfaces or Internals,
; where they should be
LUsePortB EQU 17 ; request use of printer port ;<2.0>
LFreePortB EQU 18 ; grant use of printer port ;<2.0>
LStatPortB EQU 19 ; obtain current printer port status ;<2.0>
LAPMgrPtr EQU $B18 ; This points to start of LapMgr ;<2.0>
LAPMgrCall EQU 2 ; Offset to make LAP manager calls ;<2.0>
;
; Miscellaneous patch equates
;
BInDCEOffset EQU 28 ; offset of .BIn DCE handle from UTableBase
;**************************************
; Start of async serial driver code
;**************************************
MOVE.L D0,-(SP) ; save reg D0 <PMAB401>
MOVE.L 8(SP),D0 ; get D0 = return address <PMAB401>
AND.L Lo3Bytes,D0 ; strip any junk
CMP.L #fromAOutOpen,D0 ; test for ChkAConfig call from AOutOpen
BEQ.w OpenAFix ; called for SCC channel A
CMP.L #fromAInOpen,D0 ; test for ChkAConfig call from AInOpen
BEQ.w OpenAFix ; called for SCC channel A
CMP.L #fromBOutOpen,D0 ; test for ChkBConfig call from BOutOpen
BEQ.w OpenBFix ; called for SCC channel B
CMP.L #fromBInOpen,D0 ; test for ChkBConfig call from BInOpen
BEQ.w OpenBFix ; called for SCC channel B
MOVE.L 4(SP),D0 ; get immediate return address <PMAB401>
AND.L Lo3Bytes,D0 ; strip any junk <PMAB401>
CMP.L #fromControl,D0 ; test for call from Control <PMAB401>
BEQ.w ControlFix ; called from Control <PMAB401>
CMP.L #fromStatus,D0 ; test for call from status
BEQ.w StatusFix ; called from status
CMP.L #fromClose,D0 ; test for call from Close
BEQ.w CloseFix ; called from close
CMP.L #fromInitSCC,D0 ; test for call from initSCC
BEQ.w InitSCCFix ; called from initSCC
MOVE.L (SP)+,D0 ; restore reg D0
RTS ; back to ROM
;_______________________________________________________________________
;
; Close fixes
; -- do that nutty BAP stuff to free port B
;
CloseFix
ADD.L #8,SP ; pop save reg d0 and rtrn addr--we jump back
move.l a1,-(sp) ; save DCE ptr
; for BAP
; if close is for port B,we'll just stomp over what ROM put in a6
cmpa.l #PortAVars,a6 ; from port A
beq.s @common ; yes, then move on to common code
move.l ExpandMem,a6 ; no, then get storage ptr for port B
lea ExpandMemRec.emSerdVars(a6),a6
@common
MOVE.L (A6),A2 ; get locals pointer <14Oct85>
TST.B CtlOptions(A2) ; leave DTR unchanged? <14Oct85>
bmi.s @1 ; <C216/16oct86>
bclr #7,XmitBits(A2) ; no, clear the DTR bit <C216/16oct86>
bclr #7,WR5AVal(A2) ; <C216/16oct86>
@1 bclr #3,XmitBits(A2) ; always clear Tx enable <C216/16oct86>
pea @00 ; <patch> BSR SyncOutput
move.l #SyncOutput,-(sp) ; delay until last char has cleared output buffer<14Oct85>
rts
@00
LeaROM ResetData,A3
MOVEQ #ResetLth,D1
pea @01 ; <patch> BSR initSCC1
move.l #InitSCC1,-(sp) ; shut down the channel
rts
@01
; for BAP
; we replace ROM's port arbitration stuff with BAP stuff
; too bad the ROM port arbitration code comes at the END of the close call
LEA SaveExInt(A2),A3 ; reinstall former int handlers <14Oct85>
MOVE.L (A3)+,(A5) ; <14Oct85>
MOVE.L (A3)+,(A4)+ ; <14Oct85>
ADDQ.L #4,A4 ; <14Oct85>
MOVE.L (A3)+,(A4)+ ; <14Oct85>
MOVE.L (A3),(A4) ; <14Oct85>
move.l (sp)+,a1 ; restore DCE ptr
MOVE.L DCtlStorage(A1),A0 ; get storage handle
_DisposHandle ; get rid of it
CLR.L DCtlStorage(A1) ; without a trace
CLR.L (A6) ; get rid of ptr address <14Oct85>
tst.w d3 ; what port are we?
beq.s @freeB ; port b; do that BAP thing to free port
move.l #freePort,-(sp) ; port a; finish up in ROM 2aed6
rts
@freeB
move.l ExpandMem,a0 ; <60>
tst.w ExpandMemRec.emAppleTalkInactiveOnBoot(a0) ; <60> If AppleTalk is inactive, donÕt set up the LAP manager
bnz.s @freeThePort ; <60> AppleTalk is not active.
move.l #'atkv',d0 ; what version of Appletalk? <52>
_Gestalt
tst.w d0 ; <60> Check error returned by Gestalt
bne.s @freeThePort ; <60> If an error occurred, AppleTalk is not active.
move.l a0,d0 ; get high byte (version) into low byte
rol.l #8,d0
cmp.b #53,d0 ; is Atalk version 53 or greater?
bge.s @useLAP ; yes, then call LAP manager, it exists
@freeThePort
move.l #freePort,-(sp) ; no, then finish up in ROM
rts
@useLAP move.w #LFreePortB,d0 ; call LAP Manager to free port B
move.b #useAsync,d1
move.l LAPMgrPtr,a0
jsr LAPMgrCall(a0)
move.w #0,d0 ; no error on close
rts
;_______________________________________________________________________
;
; Routine: InitSCC
; Patch: --We patch this routine to use the InitData table here in RAM
; instead of the one in ROM. We do this so that the values in
; WR11 and WR14 aren't hardcoded, so that we can support external
; clocking.
; --We also fix the value of StopBits (WR4) here to have the clock
; divide bits correspond to the the external/internal clock state
; indicated in CtlOptions. We do this here so that CtlConfig calls
; won't stomp StopBits in the ToSCCInit routine.
; --We also disable HWHS so we don't try to use CTS line for both
; clocking and handshaking.
clkBit equ 6 ; bit 6 in CtlOptions controls ext/int SCC clk
clkDvdBit equ 6 ; divide clock bit in WR4
clkMask equ %01000000 ; mask for getting at clkBit <55>
extClkSrc equ %00101000 ; SCC clk src is TRxC (CTS) pin (WR11) <55>
intClkSrc equ %01010000 ; SCC clk src is baud rate generator (WR11) <55>
BRGEnbl equ %00000001 ; enable baud rate generator (WR14) <55>
BRGDsbl equ %00000000 ; disable baud rate generator (WR14) <55>
SCCDataTable
DC.B $02,9 ; status in low bits, MIE disabled
clkDvd DC.B 4,$FF ; x16 clk, stop bits, parity options
DC.B 1,$FF ; WR1 reg, first write
DC.B 3,$FF ; bits/char option rcvr
DC.B 5,$FF ; bits/char option xmitter
DC.B $00,2 ; zero interrupt vector
DC.B $00,10 ; NRZ encoding
ClkMode DC.B $50,11 ; brgen/TRxC clk to rcvr, xmitter--default to internal
DC.B 12,$FF ; set baud rate low byte
DC.B 13,$FF ; set baud rate high byte
DC.B 3,$FF ; enable rcvr
DC.B 5,$FF ; enable xmitter
BRGEnable DC.B $01,14 ; enb/disable baud rate generator from RTxC pin --default to on
dc.b $A0,15 ; Break, CTS external ints (dcd not needed) <2.3>
DC.B $10,0 ; reset ext/status twice
DC.B $10,0
DC.B 1,$FF ; w/req pin configuration
DC.B $0A,9 ; enable interrupts, status in low bits
SCCDataTableLth EQU *-SCCDataTable ;
InitSCCFix
ADD.L #8,SP ; pop save reg d0 saved rtrn addr--we jump back
move.l a3,d0
cmpRA InitData,d0 ; are we initializing SCC?
bne @done
lea SCCDataTable,a3 ; use our RAM table instead of the ROM one
moveq #SCCDataTableLth,d1
movem.l d1/a0,-(sp) ; save out reg's <55>
; default to internally clocked state <55>
bset.b #clkDvdBit,StopBits(a2) ; default to a divide-by-16 clock <55>
moveq #intClkSrc,d0 ; internal clocking source <55>
moveq #BRGEnbl,d1 ; enable baud rate generator <55>
btst.b #clkBit,CtlOptions(a2) ; are we externally clocked?
beq.s @load ; not externally clocked, so load
; set to externally clocked state
bclr.b #clkDvdBit,StopBits(a2) ; set to a divide-by-one clock <55>
moveq #extClkSrc,d0 ; external clock source <55>
moveq #BRGDsbl,d1 ; disable baud rate generator <55>
clr.b HWHS(a2) ; make sure we're not trying to do HWHS <55>
@load lea ClkMode,a0 ; load params into InitSCC data table <55>
move.b d0,(a0) ; <55>
lea BRGEnable,a0 ; <55>
move.b d1,(a0) ; <55>
movem.l (sp)+,d1/a0 ; restore reg's <55>
@done move.l #backToInitSCC,-(sp) ; finish up in ROM
rts
;_______________________________________________________________________
;
; Routine: Status
; Patch: We patch status to add a call to return the driver's version.
StatusFix
ADD.L #8,sp ; pop save reg d0 and return addr--we jump back to ROM
MOVE.W IOTrap(A0),-(SP) ; save trap to distinguish immed calls<14Oct85>
MOVE.L A1,-(SP) ; save passed DCE for in/out <14Oct85>
MOVE.W SR,-(SP) ; disable interrupts for ctl call <14Oct85>
ORI #HiIntMask,SR ; <A357/06nov86>
LEA CSCode(A0),A0 ; get pointer to return parameters
MOVEQ #StatusErr,D0 ; assume status error
MOVE.L A2,D1 ; have our variables been set up? <14Oct85>
Bgt @stat1 ; exit if not (only input side open)<14Oct85>
move.l #ROM_CtlExit,-(sp) ; just like ROM
rts
@stat1 MOVE.W (A0)+,D1 ; get opcode
cmpi.w #9,d1 ; do we care?
beq.s @version ; yes
cmpi.w #$8000,d1 ; largest negative number csCode for Version
beq.s @version ; yes
move.l #BackToStatus,-(sp) ; no
rts
@version move.b #SerialVers,(a0) ; return the version <57>
move.l #ROM_CtlGood,-(sp)
rts
;_______________________________________________________________________
;
; Routine: Control
; Patch: We patch control for the following reasons:
; 1) to add VM support for control call 9--lock/unlock the buffer
; 2) to add external clock support in control call 16
; Called from Control - clear reg D0 in case this call is for KillIO
ControlFix
ADD.L #8,SP ; from control - flush saved reg D0 and saved return addr
CLR.L D0 ; clear reg D0 for killIO <PMAB401>
MOVE.W IOTrap(A0),-(SP) ; save trap to distinguish immed calls<14Oct85>
MOVE.L A1,-(SP) ; save passed DCE for in/out <14Oct85>
MOVE.W SR,-(SP) ; disable interrupts for ctl call <14Oct85>
ORI #HiIntMask,SR ; <A357/06nov86>
LEA CSCode(A0),A0 ; get parameters
MOVE.W (A0)+,D1 ; get opcode
cmpi #16,d1 ; opcode 16? (ctlOptions) <extClk>
beq CtlSwitchCTSClock ; <extClk>
move.l #backToBypassControl,-(sp); if not, let ROM handle it
rts
; Routine: SetCtlOptions -- Opcode 16
; Patch: We patch this routine so that bit 6 of CtlOptions variable now
; controls a switch to internal/external clocking on the CTS (HSIn) line.
; We must call InitSCC to get the clocking option to kick in.
; Inputs: byte number in IOPB value
; (26) [$0010]
; (28) bit 7 = 0 for drop DTR at close
; bit 7 = 1 for leave DTR unchanged at close
; bit 6 = 0 for internal clocking
; bit 6 = 1 for external clocking
; bits 0-5 reserved for future use
; Notes: We will not put control for the GPI internal/external
; clocking switch here, as that requires the control of
; HW external to the SCC (namely, the VIA vSync pin). Control
; of the GPIa line is in _HWPriv.
;
CtlSwitchCTSClock
move.b (a0),CtlOptions(a2) ; store new value <55>
pea @00 ; <55>
move.l #InitSCC,-(sp) ; jsr to ROM_InitSCC to set new values <55>
rts ; <55>
@00 ; <55>
move.l #ROM_CtlGood,-(sp) ; finish up in ROM <55>
rts
;_______________________________________________________________________
;
; Open Fixes
;
;
; Channel A - replace receive routine vectors installed by async open
OpenAFix
ADD.L #4,SP ; pop save reg D0 - not needed <PMAB401>
MOVE.L (SP)+,A0 ; pop A0 = addr to continue ChkConfig
move.l (sp)+,a2 ; save async open ret addr
JSR (A0) ; finish ChkConfig (A1,D1,D2 params)
move.l a2,d1 ; get Open return addr
AND.L Lo3Bytes,D1 ; strip any junk
cmp.l #fromAOutOpen,D1 ; test for ChkAConfig call from AOutOpen
beq.s @out
@in lea AsyncAIn,a2 ; store new driver header for AIn into DCE
move.l a2,(a1)
move.l #backToAInOpen,-(sp) ; jump back into ROM in AInOpen
rts
@out lea AsyncAOut,a2 ; store new driver header for AOut into DCE
move.l a2,(a1)
LEA PortAVars,A2 ; local variables address
PEA NewPollDtain ; new disk poll routine
PEA NewSCAIntHnd ; new special RxD int handler
PEA NewRAIntHnd ; new RxD int handler
move.l #ROM_TAIntHnd,-(sp) ; ROM--TxD int handler
PEA Lvl2DT+16 ; SCC interrupt dispatch table, chan A
PEA NewExtAIntHnd ; External int handler
MOVE.L #backToAOutOpen,-(SP) ; JUMP BACK INTO ROM
RTS
; Channel B - almost the same patch as channel A
; Except of course for the BAP stuff
OpenBFix
move.l ExpandMem,a0 ; <60>
tst.w ExpandMemRec.emAppleTalkInactiveOnBoot(a0) ; <60> If AppleTalk is inactive, donÕt set up the LAP manager
bnz.s @appleTalkInactive ; <60> AppleTalk is not active.
move.l #'atkv',d0 ; what version of Appletalk? <52>
_Gestalt
tst.w d0 ; <60> Did Gestalt return an error?
bne.s @appleTalkInactive ; <60> Yes, AppleTalk is inactive
move.l a0,d0 ; get high byte (version) into low byte
rol.l #8,d0
cmp.b #53,d0 ; is Atalk version 53 or greater?
bge.s @useLAP ; yes, than call LAP manager, it exists
@appleTalkInactive
; no, use old chkConfig
add.l #4,sp ; pop saved d0 -- not needed
movea.l (sp)+,a0 ; pop A0 = addr to continue non-BAP ChkConfig
move.l (sp)+,a2 ; save Open return addr
jsr (a0)
bra.s @gotPort
@useLAP add.l #8,sp ; pop d0,ROM ChkConfig addr
move.l (sp)+,a2 ; save Open return addr
movem.l a1-a2,-(sp) ; save out reg's we might use
move.w #LStatPortB,d0 ; request status of the printer port
move.l LAPMgrPtr,a0
jsr LAPMgrCall(a0)
cmp.b #useAsync,d1 ; do we already own the port?
beq.s @rstrReg ; yes
move.w #LUsePortB,d0 ; no, request use of the printer port-
move.b #useAsync,d1 ; for the serial driver-
move.l LAPMgrPtr,a0 ; by calling the LAP Manager
jsr LAPMgrCall(a0)
cmp.w #noErr,d0 ; did we get the printer port?
beq.s @rstrReg ; yes
movem.l (sp)+,a1-a2 ; no,restore reg's
rts ; return to IO Core: we already popped ret addrs and regs
@rstrReg
movem.l (sp)+,a1-a2 ; restore reg's
@gotPort
move.l a2,d1 ; get Open return addr
AND.L Lo3Bytes,D1 ; strip any junk <PMAB401>
cmp.l #fromBOutOpen,D1 ; test for ChkBConfig call from BOutOpen
beq.s @out
; from .Bin
lea AsyncBIn,a2 ; store new driver header for BIn into DCE
move.l a2,(a1)
move.l #backToBInOpen,-(sp) ; jump back into ROM in BInOpen
rts
@out; from .Bout
lea AsyncBOut,a2
move.l a2,(a1) ; store new driver header for BOut into DCE
move.l ExpandMem,a2 ; get storage ptr
lea ExpandMemRec.emSerdVars(a2),a2
CLR.L -(SP) ; no disk poll routine
PEA NewSCBIntHnd ; new special RxD int handler
PEA NewRBIntHnd ; new RxD int handler
pea NewTBIntHnd ; TxD int handler
pea Lvl2DT ; SCC interrupt dispatch table, chan A
pea NewExtBIntHnd ; External int handler
MOVE.L #backToBOutOpen,-(SP) ; JUMP BACK INTO ROM
RTS
;-----------------------------------------------------------------------
;
; Interrupt Handlers
;
;-----------------------------------------------------------------------
;_______________________________________________________________________
;
; Routine: PollDtaIn
; Arguments: A5.L (input) -- AVBufA pointer
; A6.L (input) -- SCC channel A Data pointer
; PollStack -- start of stack data
; This routine should be jsr'ed to, with polled input data
; on the stack (high-order bytes between current SP+4 and
; PollStack address).
; Function: Processes input data from disk driver polling.
AsyncPRAddr EQU PollRtnAddr ; don't use DskRtnAddr because Sony driver uses it
NewPollDtaIn
MOVE.L PollStack,A4 ; start of data
MOVE.L (SP)+, AsyncPRAddr ; save return address <01Feb85>
StorData TST.B (A5) ; SCC data available?
BMI.S @1
MOVE.B (A6),-(SP) ; push it on the stack
BRA.S StorData ; get it emptied out . . .
@1 CMP.L SP,A4 ; processed all data?
BEQ.S @2 ; exit if so
SUBQ #2,A4 ; skip over garbage byte
MOVE.B (A4),D0 ; get next byte
LEA PortAVars,A3 ; get appropriate variables (channel A)
LEA SCCRBase+ACtl,A0 ; and SCC pointers for RxBF routine
LEA SCCWBase+ACtl,A1
BSR.S PollStash ; store it, using our RxBF routines
BRA.S StorData
@2 MOVE.L #backToPollDtain,-(SP) ; <patch> JUMP BACK TO ROM
RTS ; <patch>
;________________________________________________________________________
;
; Routine: RXIntHnd
;
; Arguments: A0 (input) -- chan A/B control read address
; A1 (input) -- chan A/B control write address
;
; Function: This routine handles SCC receiver interrupts for
; both channels; the data is read and stashed, IODone called
; if necessary.
;________________________________________________________________________
NewRBIntHnd
move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars
move.l ExpandMemRec.emSerdVars(a2),a2
movea.l UTableBase,a3 ; get .Bin DCE ptr in a3
movea.l BInDCEOffset(a3),a3
movea.l (a3),a3
MOVE.B SCCData(A0),D0 ; get the data byte
bra.s PS1 ; and branch around 'redundant' 6.X code
NewRAIntHnd LEA PortAVars,A3 ; get appropriate variables (chan A)
RXIntHnd MOVE.B SCCData(A0),D0 ; get the data byte
PollStash MOVE.L (A3)+,A2 ; get pointer to local variables
MOVE.L (A3),A3 ; and DCE pointer
PS1 AND.B CharMask(A2),D0 ; zero unused high bits <14Oct85>
MOVE.B PEChar(A2),D1 ; Are we translating PE Characters?
BEQ.S @1 ; No, just save the char.
CMP.B D1,D0 ; Is the new char a PEChar?
BNE.S @1 ; No, just do normal stuff
MOVE.B AltChar(A2),D0 ; Make sure that a good char <14Oct85>
; doesn't look like PEChar.
@1 TST.B SWHS(A2) ; software handshake enabled?
BEQ.S StashIt ; branch if not
CMP.B XONChar(A2),D0 ; was this an XON? <14Oct85>
BNE.S @2 ; <patch>
MOVE.L #ToContOut,-(SP) ; <patch> BEQ.S ContOut
RTS ; <patch>
@2 CMP.B XOFFChar(A2),D0 ; how about an XOFF? <14Oct85>
BNE.S StashIt ; if not, then stash the character
ST XOFFlag(A2) ; if so, then note it
BRA InputRTS ; and exit
; stash byte in the user's buffer if a request is pending, otherwise use our own
StashIt TST.B ReadCmd(A2) ; read request pending?
BEQ.S PutInOurBuf ; if there isn't one, stash it in ours
PutInUserBuf
MOVE.L A3,A1 ; get DCE pointer
PEA @1 ; <patch> BSR.S toStash
MOVE.L JStash,-(SP) ; <patch>
RTS ; <patch>
@1 BPL.S InputRTS ; if request isn't finished, just RTS
CLR.B ReadCmd(A2) ; no longer a read request pending
MOVE.L #ToGoodFinish,-(SP) ; <patch> BRA.S GoodFinish
RTS ; <patch>
PutInOurBuf
PEA @00 ; <patch> BSR GetBufRegs
MOVE.L #ToGetBufRegs,-(SP) ; <patch>
RTS ; <patch>
@00 ; <patch>
MOVE.B D0,0(A3,D1.W) ; stash the byte
ADDQ.W #1,D1 ; update BufIndex
CMP.W D3,D1
BNE.S @1 ; br if not at the end
MOVEQ #0,D1 ; otherwise, reset to 0
@1 CMP.W D2,D1 ; hit the output index?
BNE.S @2 ; br if not
BSET #SoftOR,AsyncErr(A2); note the soft overrun
BRA.S InputRTS ; and exit without updating index
@2 MOVE.W D1,BufIndex(A2) ; update index
TST.W InSWHS(A2) ; XON/XOFF or DTR input flow control?<14Oct85>
BEQ.S InputRTS ; br if not
PEA @11 ; <patch> BSR.S GetBufCnt
MOVE.L #ToGetBufCnt,-(SP) ; <patch>
RTS ; <patch>
@11 ; <patch>
SUB.W D0,D3 ; bytes to top
CMP.W BufHigh(A2),D3 ; past the max limit?
BCC.S InputRTS ; exit if not
TST.B InHWHS(A2) ; input DTR flow control? <14Oct85>
BNE.S @4 ; <patch>
MOVE.L #ToCtlXOff,-(SP) ; <patch> BEQ.S CtlXOff
RTS ; <patch>
@4 BSET #6,FlowOff(A2) ; have we negated DTR? <14Oct85>
BEQ.S @3 ; <patch>
MOVE.L #ToPut,-(SP) ; <patch> HERE'S THE ONE LINE THAT CHANGED - BNE.S @3
RTS ; <patch>
@3 MOVE.L #backToPut,-(SP) ; <patch> JUMP BACK TO ROM
InputRTS RTS ; <patch>
;________________________________________________________________________
;
; Routine: SCIntHnd
;
; Arguments: A0 (input) -- channel A/B control read address
; A1 (input) -- channel A/B control write address
;
; Function: This routine handles SCC special condition interrupts:
; these occur when an input character is received that has
; a parity error, framing error, or causes an overrun.
; If the option is set to abort on the error, the character
; is discarded and the input request (if any) aborted; otherwise,
; the error is noted and the character buffered as usual.
; Patch: forBAP, get driver storage ptr from expanded mem
; get DCE ptr from UTable
NewSCBIntHnd
move.l ExpandMem,a3 ; use ExpandMem instead of PortBVars
move.l ExpandMemRec.emSerdVars(a3),a2
movea.l UTableBase,a3 ; get .Bin DCE ptr in a3
movea.l BInDCEOffset(a3),a3
movea.l (a3),a3
bra.s SC1 ; and branch around port a code code
NewSCAIntHnd
LEA PortAVars,A3 ; get appropriate variables (chan A)
SCIntHnd
MOVE.L (A3)+,A2 ; get local variables pointer
MOVE.L (A3),A3 ; and DCE pointer (delay, too)
SC1 MOVE.B #1,(A1) ; point to error reg
MOVE.B (A0),D1 ; read the error condition
MOVEQ #$70,D3 ; form $70 mask
AND.B D3,D1 ; isolate error bits
OR.B D1,AsyncErr(A2) ; accumulate errors (delay, too)
MOVE.B SCCData(A0),D0 ; get the data byte
AND.B CharMask(A2),D0 ; zero unused high-order bits <14Oct85>
MOVE.B Options(A2),D2 ; get abort options
AND.B D1,D2 ; should we abort?
MOVE.B #$30,(A1) ; reset the error flag
AND.B D3,D2
BNE.S @2 ; br if we should abort . . .
MOVE.B PEChar(A2),D3 ; alternate char for parity errors?
BEQ.S @1 ; br if not
CMP.B D0,D3 ; Is the incoming char equal to the PEChar?
BNE.S @0 ; No, no substitution needed.
MOVE.B AltChar(A2),D0 ; Make sure that a good char <14Oct85>
; doesn't look like PEChar.
@0 BTST #4,D1 ; parity error?
BEQ.S @1 ; br if not
MOVE.B D3,D0 ; replace it
@1 BRA StashIt ; go stash it . . .
@2 TST.B ReadCmd(A2) ; if we have no pending read command
BEQ.S InputRTS ; then just discard the character
MOVEQ #RcvrErr,D0 ; otherwise, note the error
MOVE.L #ToRdReqDone,-(SP) ; <patch> JUMP BACK TO ROM
RTS ; <patch>
;________________________________________________________________________
;
; Routine: TBIntHnd
; for BAP
; Get the variables ptr from expand mem for the interrupt handlers
;
NewTBIntHnd
move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars
move.l ExpandMemRec.emSerdVars(a2),a2
JmpRom backToTXIntHnd ; back to ROM
;________________________________________________________________________
;
; Routine: ExtIntHnd
; for BAP
; Get the variables ptr from expand mem for the interrupt handlers
; Get input DCE ptr from the Unit Table
;
; -- patch to set bit 3 in AsyncErr (had to patch in ALL code before).
; -- also fix the RdReqDone problem
NewExtBIntHnd
move.l ExpandMem,a3 ; use ExpandMem instead of PortBVars
move.l ExpandMemRec.emSerdVars(a3),a2
movea.l UTableBase,a3 ; get .BIn DCE ptr in a3
movea.l 28(a3),a3
movea.l (a3),a3
bra.s ExtIntHnd
NewExtAIntHnd
LEA PortAVars,A3 ; get appropriate variables - chan A
MOVE.L (A3)+,A2 ; get pointer to local variables
MOVE.L (A3),A3 ; get .AIn DCE ptr in a3
ExtIntHnd
MOVE.B D1,D2 ; changed bits
AND.B postOptions(A2),D2 ; post this change?
BEQ.S @0 ; br if not
MOVEM.L D0/A0,-(SP) ; preserve these registers
MOVE.W #IODrvrEvt,A0
ASL.W #8,D0 ; make room for 'changed' values
MOVE.B D1,D0
SWAP D0 ; make room for input driver refnum
MOVE.W DCtlRefnum(A3),D0
_PostEvent ; and post the event
MOVEM.L (SP)+,D0/A0
@0 TST.B D1 ; see if it's a change in break status
BMI.S extBreak ; branch if it was a break interrupt
LSL.B #2,D0 ; must be CTS change
SMI CTSFlag(A2) ; set flags according to CTS
; This piece of code is used to detect a clock into the HWHS line
; and shut off the ext/sts interrupt for the handshake line.
CMP.W #80,HSCount(A2) ; exceeded 80 transitions in 16 MS? <14Oct85>
BCS.S @2 ; br if not <14Oct85>
MOVEQ #-128,D0 ; ($80) leave break ints enabled <14Oct85>
MOVEQ #15,D1 ; write register 15 <14Oct85>
pea @00 ; bsr CtlSet
move.l #ToCtlSet,-(sp) ; <patch>
rts
@00
@2 MOVE.L Ticks,D2 ; get current tick time <14Oct85>
CMP.L LastTime(A2),D2 ; same as last? <14Oct85>
BEQ.S @3 ; br if so <14Oct85>
MOVE.L D2,LastTime(A2) ; new last time <14Oct85>
CLR.W HSCount(A2) ; restart count for new time <14Oct85>
@3 ADDQ #1,HSCount(A2) ; update count <14Oct85>
move.l #toContOut1,-(sp) ;<patch> BRA ContOut1--if freshly asserted, continue output<14Oct85>
rts
extBreak TST.B D0 ; check break level
BMI.S @1 ; if it's asserted, terminate any input
MOVE.B SCCData(A0),D0 ; otherwise (end of break), discard null
@done RTS ; and return <2.5>
@1 MOVEQ #BreakRecd,D0 ; note the break
bset.b #3,AsyncErr(a2) ; we now note break level in status
TST.B ReadCmd(A2) ; read request pending?
BEQ.S @done ; no, then just return <2.5>
move.l #ToRdReqDone,-(sp) ; a3 has input DCE ptr
rts
;_______________________________________________________________________ <52>
;
; Patched Driver headers (with signature long word before each header)
;
DC.b 'wong' ; our personal signature
AsyncAIn
DC.W $4D00 ; read, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W AInOpen-AsyncAIn ; Initialization routine
DC.W AInPrime-AsyncAIn ; input Prime routine
DC.W AControl-AsyncAIn ; shared Control routine
DC.W AStatus-AsyncAIn ; shared Status routine
DC.W AInClose-AsyncAIn ; Close routine
DC.B 4 ; channel A input driver
DC.B '.AIn '
DC.b 'wong' ; our personal signature
AsyncAOut
DC.W $4E00 ; write, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W AOutOpen-AsyncAOut ; Initialization routine
DC.W AOutPrime-AsyncAOut ; output Prime routine
DC.W AControl-AsyncAOut ; shared Control routine
DC.W AStatus-AsyncAOut ; shared Status routine
DC.W AOutClose-AsyncAOut ; Close routine
DC.B 5 ; channel A output driver
DC.B '.AOut'
DC.b 'wong' ; our personal signature
AsyncBIn
DC.W $4D00 ; read, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W BInOpen-AsyncBIn ; Initialization routine
DC.W BInPrime-AsyncBIn ; input Prime routine
DC.W BControl-AsyncBIn ; shared Control routine
DC.W BStatus-AsyncBIn ; shared Status routine
DC.W BInClose-AsyncBIn ; Close routine
DC.B 4 ; channel B input driver
DC.B '.BIn '
DC.b 'wong' ; our personal signature
AsyncBOut
DC.W $4E00 ; write, control, status, lock
DC.W 0,0 ; not an ornament
DC.W 0 ; no menu
DC.W BOutOpen-AsyncBOut ; Initialization routine
DC.W BOutPrime-AsyncBOut ; output Prime routine
DC.W BControl-AsyncBOut ; shared Control routine
DC.W BStatus-AsyncBOut ; shared Status routine
DC.W BOutClose-AsyncBOut ; Close routine
DC.B 5 ; channel B output driver
DC.B '.BOut'
;_______________________________________________________________________ <52>
;
; jumping to ROM from our patched entry points
;
AInOpen jmp ROM_AInEntryOpen ;port a
AInClose jmp ROM_AInEntryClose
AInPrime jmp ROM_AInEntryPrime
AOutOpen jmp ROM_AOutEntryOpen
AOutClose jmp ROM_AOutEntryClose
AOutPrime jmp ROM_AOutEntryPrime
AControl jmp ROM_AEntryControl
AStatus jmp ROM_AEntryStatus
BInOpen move.l #backToBInOpenStart,-(sp) ; port b
rts
BOutOpen move.l #backToBOutOpenStart,-(sp)
rts
BInClose moveq #0,d0 ; shorter to return than to jump to ROM
rts
BOutClose move.l #ToBOutClose,-(sp) ; don't need to screw with this other than patch above
rts
BInPrime
move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars
move.l ExpandMemRec.emSerdVars(a2),a2 ;
move.l #backToBInPrime,-(sp) ; location to return to BInPrime
rts
BOutPrime
move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars
move.l ExpandMemRec.emSerdVars(a2),a2 ;
move.l #backToBOutPrime,-(sp) ; location to return to BOutPrime
rts
BControl
move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars
move.l ExpandMemRec.emSerdVars(a2),a2 ;
move.l #backToBControl,-(sp) ; location to return to BControl
rts
BStatus
move.l ExpandMem,a2 ; use ExpandMem instead of PortBVars
move.l ExpandMemRec.emSerdVars(a2),a2 ;
move.l #backToBStatus,-(sp) ; location to return to BStatus
rts
;
; End of Async.a Patch <51><52>
;_____________________________________________________________________________________________
;____________________________________________________________________________________
; PA511 -- UpdAltMDB patch
;
; This patch fixes a problem that occurs when an HFS alternate MDB is to be
; updated on a SuperDrive 1440k floppy. The problem occurs due to the way
; the routine UpdAltMDB determines the size of a floppy disk. The driver
; for the SuperDrive implements a Status call that returns a drive size list.
; We attempt to use this Status call, and if it fails, default to the old
; way of determining drive size (1-sided, 2-sided flag in the DQE).
;
; Due to the fact that the UpdAltMDB routine is not vectored, this patch
; dynamically patches out GetBlock for the duration of all calls to ExtBTFile
; so that GetBlock checks for a call from within the UpdAltMDB routine.
; If detected, the above method of determining disk size is employed
; and the result placed in register D2, where it is later used to
; read/write the alternate MDB. Afterwards, the GetBlock "come-from"
; patch is undone until the next instance of a call to ExtBTFile.
;
; PA511 24Jun88 JB Added patch to fix UpdAltMDB to use correct disk address
; on 1440k disks
; PA548 27Jul88 JB Modified to not make 'Get Format List' Status call unless
; doing so to the Sony driver. Fixes problems with 3rd party
; disks that either die, return garbage, or ignore CSCode
; altogether. Hope this can change someday...
;____________________________________________________________________________________
AltMDBPatch PROC
EXPORT MyExtBTF,svExtBTFile
;
; Format List record returned by the SuperDrive version of the Sony Driver
;
; One record per possible drive configuration is returned on a
; Status call with csCode = 6. The entry with bit 6 in flflags set
; is the 'current disk' configuration and is the entry used to
; determine drive size.
;
FmtLstRec record 0 ;
frsize ds.l 1 ; Disk size in BYTES
frflags ds.b 1 ; flags
frspt ds.b 1 ; sectors per track
frtracks ds.w 1 ; total # of tracks
flrecsize equ * ; size of the format list record
endr
NFRecs equ 16 ; max # of FmtLstRec to allocate on the stack
;
; Save cells for some vectors:
;
svExtBTFile ds.l 1
svGetBlock ds.l 1
;
; "Come from" address for call to GetBlock out of the
; UpdAltMDB routine:
;
fromUAMDB EQU $408b84 ; SE=$408b84, MacII=$4080c648
MyExtBTF
;
; Install our GetBlock patch for the duration of this
; ExtBTFile call...
;
lea svGetBlock,a0 ; Install our GetBlock filter
move.l JGetBlock,(a0) ; ...for the duration of
lea MyGetBlock,a0 ; ...the call to ExtBTFile
move.l a0,JGetBlock ; We now "see" all GetBlock calls...
;
; Call the real ExtBTFile routine
;
move.l (sp)+,-(a6) ; Save async return address
pea @0 ; Where the real ExtBTFile will return...
move.l svExtBTFile,-(sp) ; Fake a JSR to the real ExtBTFile
rts
@0
;
; After calling ExtBTFile, undo the temporary patch to GetBlock...
;
lea svGetBlock,a0 ; Restore the real GetBlock routine
move.l (a0),JGetBlock ; ...vector (ROM **or** RAM Cache)
move.l (a6)+,-(sp) ; Restore our return addr
tst.w d0 ; Set condition codes
rts ; ...bye
;__________________________________________________________________
; This is where the real work is done. If this GetBlock filter
; catches a call from within the UpdAltMDB routine, we fudge the
; contents of D2, which is the block address of the alternate MDB.
;__________________________________________________________________
MyGetBlock
cmp.l #fromUAMDB,(sp) ; Call from within UpdAltMDB?
bne doGetBlock ; No, just do the old GetBlock...
;
; Get here on the call to GetBlock that we are looking for.
; Determine the real size of the disk and update D2 appropriately.
;
WITH FmtLstRec
movem.l a0/a2/d0/d1,-(sp) ; Save what we use...
;
; Try the Sony Driver control call to attempt to discover
; drive size. If it fails, revert to the old assumptions...
;
sub.w #NFRecs*flrecsize,sp ; Make space for the format records
move.l sp,a2 ; Save format record buffer address
;
; Push an ioparamblk on the stack
;
moveq #(ioQElSize+1)/2-1,d0 ;
@1 clr.w -(sp) ;
dbf d0,@1 ;
move.l sp,a0 ; Parameter block address
; Check here for Sony driver because 3rd party disk drivers don't <JB/27Jul88>
; correctly support _Status calls. Some don't even check the value <JB/27Jul88>
; of the CSCode parameter!!! For now, don't call any driver except <JB/27Jul88>
; our own Sony driver. Maybe someday we'll get all drivers to support <JB/27Jul88>
; the 'Format List' status call... <JB/27Jul88>
moveq #0,d2 ; Vol size in 512-byte blocks if not a Sony <JB/27Jul88>
move.w dQDrvSz(a3),d2 ; <JB/27Jul88>
cmp.w #dskRfN,dQRefNum(a3) ; Is this a Sony drive? <JB/27Jul88>
bne.s ckVersn ; Skip Status call if not, check DQE version...<JB/27Jul88>
move.w dQDrive(a3),ioVRefNum(a0) ; drive number
move.w dQRefNum(a3),ioRefNum(a0) ; driver refnum
move.w #FmtLstCode,csCode(a0) ; Opcode for 'Return Format List'
move.w #NFRecs,csParam(a0) ; max number of format records to return
move.l a2,csParam+2(a0) ; ptr to place to return format records
_Status ; Ask driver for drive sizes
bne.s guessiz ; If any error, guess the size...
;
; Scan the returned list of format records for the entry which
; describes the 'current disk'.
;
move.w csParam(a0),d0 ; Number of format entries returned
beq.s guessiz ; Go guess if driver returned zilch...
sub.w #1,d0 ; ...for DBF loop
@2
btst #6,frflags(a2) ; Is this entry for the 'current disk'
bne.s @3 ; Xfer if so...
add.w #flrecsize,a2 ; Else, point to next record
dbf d0,@2 ; ...and try again
bra.s guessiz ; No 'current disk' found, go guess...
@3
move.l frsize(a2),d2 ; Get drive size in BLOCKS
bra.s GVSzExit ; And return...
;
; Attempt to determine the drive size by looking at the
; drive queue element. This method used for any driver not
; supporting the control call.
;
guessiz:
move.w #800,d2 ; assume single-sided sony
tst.b dQDrvSz(a3) ; TwoSideFmt?
beq.s ckVersn ; br if not <JB/27Jul88>
add.l d2,d2 ; two-sided, double size
ckVersn: ; <JB/27Jul88>
tst.w qType(a3) ; new version element?
beq.s GVSzExit ; br if not
move.l dQDrvSz(a3),d2 ; it's a long in the new world
swap d2 ; but swapped for compatibility
GVSzExit
add.w #ioQElSize+(NFRecs*flrecsize),sp ; Discard stuff on the stack
movem.l (sp)+,a0/a2/d0/d1 ; Restore scratch registers
ENDWITH
subq #2,d2 ; Convert disk size in blocks to alt MDB address
;__________________________________________________________________
; Do the actual GetBlock call -- D2 adjusted, if necessary
;__________________________________________________________________
doGetBlock
move.l svGetBlock,-(sp) ; Continue in the real GetBlock...
rts
ENDPROC ; **** End of AltMDBPatch patch ****
;____________________________________________________________________________________
; PP332 Cache control trap
;
; This patch adds a new trap to programatically control parameters of the RAMCache.
;
;
; Function: These traps provide an interface to the file system
; caching mechanism.
;
; Cache Trap
; Routines:
; GetCSize Get cache size
; SetCSize Set cache size
; GetApZnSiz Get minimum application zone size
; SetApZnSiz Set minimum application zone size
; GetMaxCXfr Get maximum cached transfer size
; SetMaxCXfr Set maximum cached transfer size
; GetCStatus Get cache status
; SetCStatus Get cache status
;
; Internal
; Routines:
; GetCacSize Get current size of cache
;
; To do:
; Need to completely redefine way cache uses memory. Should be
; a trap here to feed memory to the cache (called by MultiFinder
; or memory manager), also a way to ask for those blocks back
; if they are needed.
; Need some reasonableness checks for parameters.
;
; Modification History:
;
; <20Nov87> JB New today.
; <25Nov87> JB Added get/set cache status
; <02Dec87> JB Changed for ioParamblock interface
; <20Feb89> JB/DNF Moved from BeforePatches.a
;_____________________________________________________________________________
;_____________________________________________________________________________
; Cache trap dispatcher
;
; Supplied:
; D0.W Service selector index
; A0.L New cache parameter value if call is a 'set' call
;
; Returned:
; D0.L Result code
; 'ParamErr' is returned if either the selector
; is invalid or if the value supplied on a 'set'
; call is unreasonable
; A0.L Requested cache parameter value if the
; call was a 'get' call
;_____________________________________________________________________________
CachePatch PROC EXPORT
ROMFSQSync equ $4042e8 ; Mac SE FSQueueSync address
ROMCmdDone equ $4043a0 ; Mac SE CmdDone address
ioMisc equ $1C ; old ioMisc mnemonic--need appropriate new name
;_____________________________________________________________________________
; Cache trap dispatch table:
;_____________________________________________________________________________
CTrapTbl dc.w GetCSize-CTrapTbl ; 0 - get cache size
dc.w SetCSize-CTrapTbl ; 1 - set cache size
dc.w GetApZnSiz-CTrapTbl ; 2 - get min application zone size
dc.w SetApZnSiz-CTrapTbl ; 3 - set min application zone size
dc.w GetMaxCXfr-CTrapTbl ; 4 - get max cached transfer size
dc.w SetMaxCXfr-CTrapTbl ; 5 - set max cached transfer size
dc.w GetCStatus-CTrapTbl ; 6 - get cache status
dc.w SetCStatus-CTrapTbl ; 7 - set cache status
maxCacheTrap equ (*-CTrapTbl)/2 ; Number of traps defined
EXPORT CacheTrap
CacheTrap cmp.w #maxCacheTrap,d0 ; Valid trap index?
blo.s @1 ; Xfer if so...
moveq #ParamErr,d0 ; Else, indicate parameter error
rts
@1
lea CTrapTbl,a1 ; Base of dispatch table
add.w d0,d0 ; Trap index into WORD index
add.w (a1,d0),a1 ; Routine to invoke
jmp (a1) ; Go to requested routine...
CTExit
jmp ROMCmdDone ; Exit via the file system...
;_____________________________________________________________________________
; 0 -- Get cache size
;_____________________________________________________________________________
GetCSize
jsr ROMFSQSync ; Synchronize with the file manager
move.l CacheVars,a1 ; Cache vars address
move.l OldBufPtr(a1),d0 ; Pre-cache BufPtr
sub.l NewBufPtr(a1),d0 ; Size of cache = (Pre-cache BufPtr)-current
move.l d0,ioMisc(a0) ; Return in param block
moveq #0,d0 ; Result = SUCCESS
bra.s CTExit
;_____________________________________________________________________________
; 1 -- Set cache size
;_____________________________________________________________________________
SetCSize
jsr ROMFSQSync ; Synchronize with the file manager
move.l ioMisc(a0),d0 ; Get desired cache size
moveq #15,d1 ; Divide by 32K
lsr.l d1,d0 ; ...
move.b d0,CacheConfig ; Set mem config for next launch
moveq #0,d0 ; Result = SUCCESS
bra.s CTExit
;_____________________________________________________________________________
; 2 -- Get minimum application zone size
;_____________________________________________________________________________
GetApZnSiz
jsr ROMFSQSync ; Synchronize with the file manager
move.l CacheVars,a1 ; Cache vars address
move.l CacheMinZn(a1),ioMisc(a0)
moveq #0,d0 ; Result = SUCCESS
bra.s CTExit
;_____________________________________________________________________________
; 3 -- Set minimum application zone size
;
; This value is examined whenever the cache is grown. Cache size will
; not be allowed to exceed this amount. The default value is enough
; space to load and run an application. The value may be set to a
; smaller value to enable use of memory for cacheing when it is known
; that other applications will not be present (MultiFinder).
;_____________________________________________________________________________
SetApZnSiz
jsr ROMFSQSync ; Synchronize with the file manager
move.l CacheVars,a1 ; Cache vars address
move.l ioMisc(a0),CacheMinZn(a1) ; Set new ApplZone size minimum
moveq #0,d0 ; Result = SUCCESS
bra.s CTExit
;_____________________________________________________________________________
; 4 -- Get maximum cached transfer size
;_____________________________________________________________________________
GetMaxCXfr
jsr ROMFSQSync ; Synchronize with the file manager
move.l CacheVars,a1 ; Cache vars address
move.l CacheByteLim(a1),ioMisc(a0)
moveq #0,d0 ; Result = SUCCESS
bra.s CTExit
;_____________________________________________________________________________
; 5 -- Set maximum cached transfer size
;
; This value is examined on each "read/write in place" call. These cache
; calls are used by file system to transfer integral blocks from the
; caller's buffer to/from the disk (possibly) without caching. Setting
; this value to a smaller value will tend to keep reading/writing large
; files from effectively causing a flush of the cache. This might
; make an environment where multiple files are typically open behave
; better (i.e., one application won't tend to cause the cache to be
; flushed).
;_____________________________________________________________________________
SetMaxCXfr
jsr ROMFSQSync ; Synchronize with the file manager
move.l CacheVars,a1 ; Cache vars address
move.l OldBufPtr(a1),d0 ; Pre-cache BufPtr
sub.l NewBufPtr(a1),d0 ; Size of cache = (Pre-cache BufPtr)-current
move.l ioMisc(a0),d1 ; Get caller's parameter
cmp.l d1,d0 ; Cache size >= requested max xfer size?
bhs.s @1 ; Xfer if so...
moveq #ParamErr,d0 ; Else, indicate parameter error
bra CTExit
@1
move.l d1,CacheByteLim(a1) ; Set new max transfer size
moveq #0,d0 ; Result = SUCCESS
bra CTExit
;_____________________________________________________________________________
; 6 -- Get cache status
;_____________________________________________________________________________
GetCStatus
jsr ROMFSQSync ; Synchronize with the file manager
move.l CacheVars,a1 ; Cache vars address
moveq #0,d0 ; Assume cache disabled
tst.b CurEnable(a1) ; Cache currently enabled?
beq.s @1 ; Xfer if currently disabled (error?)
btst #5,CacheEnable ; test enable bit
beq.s @1 ; Xfer if disabled
moveq #1,d0 ; Else, indicate "enabled"
@1
move.l d0,ioMisc(a0) ; Set returned cache status to caller
moveq #0,d0 ; Result = SUCCESS
bra CTExit
;_____________________________________________________________________________
; 7 -- Set cache status
;_____________________________________________________________________________
SetCStatus
jsr ROMFSQSync ; Synchronize with the file manager
tst.l ioMisc(a0) ; Enable or disable?
beq.s @1 ; Xfer if disable...
bset #5,CacheEnable ; Else, ask for enable on next launch
bra.s @2
@1
bclr #5,CacheEnable ; Ask for disable on next launch
@2
moveq #0,d0 ; Result = SUCCESS
bra CTExit
;_____________________________________________________________________________
;********************** End of Cache control trap ****************************
;_____________________________________________________________________________
ENDPROC
;____________________________________________________________________________________
; P005 S118 MapFBlock patch:
;
; This patch fixes a problem in MapFBlock which was trashing the extent file.
; MapFBlock was adding a word value rather than a long word value during the
; calculation of starting logical block number. This resulted in a wrap-
; around of the block number (modulo 64K). Since the extent file resides at
; allocation block zero, it was the first file to be trashed.
;
; This patch applies to ROM76 - ROM78 only. A separate patch in ROM75Fix
; (PM119) is required for ROM75. This is due to the absense of MapFBlock and
; XFSearch vectors in ROM75.
;
; Patched using the "MapFBlock" vector. NOTE, this patch replaces the
; "jMapFBlock" vector without saving the previous contents of that vector!
;
; The corresponding source code modification for this patch were made to
; FXM.a in the "MapFBlock" routine. The required modification was simply
; changing "ADD.W D0,D3" to "ADD.L D0,D3" when calculating the physical
; start block address.
;____________________________________________________________________________________
MapFBPatch: PROC EXPORT
MOVE.L (SP)+,-(A6) ; save return address on A6 stack
MOVEM.L D1-D2/D4-D5/D7/A0-A1/A3-A4,-(A6) ; save registers
SUB #lenFXVars,A6 ; allocate memory for FXM vars <19Mar87>
MOVEA.L A6,A4 ; A4 = pointer to FXM vars <19Mar87>
CLR.B FXVFlags(A4) ; clear all flags <19Mar87>
LEA 0(A1,D1.W),A3 ; A3 = FCB pointer
;
; locate the extent mapping the desired file position
;
MOVE.L D5,D0 ; file position
MOVEA.L jXFSearch,A0 ; call XFSearch via its vector <19Mar87>
JSR (A0) ; <19Mar87>
BNE.S MFExit ; exit on errors
LEA 0(A1,D1.W),A1 ; A1 = ptr to extent entry
MOVE.W D3,D1 ; D1 = beg FABN for extent
SUB.W xdrNumABlks(A1),D1 ;
MOVE.W D3,D2 ; D2 = end FABN in extent + 1
;
; determine end of available space (PEOF or end of extent)
;
MULU VCBAlBlkSiz+2(A2),D2 ; convert end FABN + 1 to file pos
MOVE.L FCBPLen(A3),D0 ; get PEOF
CMP.L D0,D2 ; end of extent > PEOF?
BLE.S @1 ; no, use end of extent ->
MOVE.L D0,D2 ; yes, use PEOF
@1 DIVU VCBAlBlkSiz+2(A2),D2 ; D2 = end of avail space ( end FABN + 1)
;
; set up some constants
;
MOVE.L VCBAlBlkSiz(A2),D6 ; D6 = # blks per alloc blk
DIVU #512,D6 ;
MOVEQ #0,D7 ; D7 = start blk # for alloc blks
MOVE.W VCBAlBlSt(A2),D7 ;
;
; calculate physical start block
;
MOVE.L D5,D3 ; file position / alloc blk size
DIVU VCBAlBlkSiz+2(A2),D3 ; = FABN mapping file position
SWAP D3 ; Get remainder in low word <PWD 26Sep85>
MOVEQ #0,D0 ; Clear top word to get remainder as long <PWD 26Sep85>
MOVE.W D3,D0 ; Compute block offset within alloc block <PWD 26Sep85>
LSR.L #8,D0 ; 'divide' by 256 <PWD 26Sep85>
LSR.L #1,D0 ; and again by 2 to get size in phys. blocks <PWD 26Sep85>
SWAP D3 ; Restore D3 for use <PWD 26Sep85>
SUB.W D1,D3 ; - beg FABN = alloc blk delta
ADD.W xdrStABN(A1),D3 ; + starting ABN = ABN mapping file pos
MULU D6,D3 ; convert to physical block #
ADD.L D0,D3 ; Offset in physical blocks within alloc. blk <19Mar87>
ADD.L D7,D3 ;
;
; calculate number of available bytes
;
MOVE.W D2,D6 ; end FABN + 1 * alloc blk size
MULU VCBAlBlkSiz+2(A2),D6 ; = ending file pos + 1
SUB.L D5,D6 ; - file position = size avail
CMP.L D4,D6 ; compare with desired number
BCS.S mFBlockOK ; < D4 bytes, leave it alone <02Oct85>
MOVE.L D4,D6 ; > D4 bytes, set to D4 bytes
mFBlockOK MOVEQ #0,D0 ; we're ok <01Oct85>
;
; clean up and exit
;
MFExit
ADD #lenFXVars,A6 ; de-allocate memory for FXM vars <02Oct85>
MOVEM.L (A6)+,D1-D2/D4-D5/D7/A0-A1/A3-A4 ; restore registers
MOVE.L (A6)+,-(SP) ; put return address back on stack
TST.W D0 ; set CCR for result <01Oct85>
RTS ; exit MapFBlock
ENDPROC
;____________________________________________________________________________________
; * * * End of MapFBlock patch * * *
;____________________________________________________________________________________
;_______________________________________________________________________
;<2.7> Deferred Task Manager _DTInstall Trap, vDisptch
; EH Interrupt Handlers Lvl1Int, Lvl2Int, Lvl3Int
;
; This patch adds the deferred task manager code, which consists of the
; _DTInstall Trap and the vDisptch routine, to the MacSE.
;
; To add the manager, we must also patch out the interrupt handlers,
; since they are what call the vDisptch routine, which executes the
; deferred tasks.
;
; The code is lifted whole-heartedly from Gary Davidian's inthnd and
; DTCore files.
;
;_______________________________________________________________________
DeferredTaskPatch proc
export DTInstall ; Trap for installing deferred tasks
export vDisptch ; Deferred task handler
export level1Int ; level 1 primary interrupt handler
export level2Int ; level 2 primary interrupt handler
export level3Int ; level 3 primary interrupt handler
; Private equates for interrupt handlers
IntRegs reg a0-a3/d0-d3 ; registers saved by all interrupt handlers
IntRegsSize equ 8*4 ; size of IntRegs in bytes, must change if IntRegs changes
; Rename a few historical equates for clarity
Via1DT equ Lvl1DT ; Dispatch table for VIA1 interrupts
SccDT equ Lvl2DT ; Dispatch table for SCC interrupts
;_______________________________________________________________________
;
; Auto-Vector Interrupts on Mac Plus/SE
;
; The auto-vectors are assigned as below (according to interrupt priority level):
;
; Level 1: VIA1 interrupts, dispatched through Via1Int using Via1DT.
;
; Level 2: SCC interrupts, dispatched through SccDecode using SccDT.
; For HcMac, the Apple Sound Chip Interrupt is OR'ed with this interrupt. If
; the dispatcher determines that the SCC was not responsible, then the sound driver
; interrupt handler is called.
;
; Level 3: Simultaneous VIA1 and SCC interrupts, will revert to a level 2 interrupt.
;_______________________________________________________________________
Level3Int rte ; just return, it will revert to level 2
Level2Int movem.l IntRegs,-(SP) ; preserve registers
lea SccDecode,a3 ; use the SCC interrupt dispatcher
bra.s ServiceInt ; call primary interrupt dispatcher
Level1Int movem.l IntRegs,-(SP) ; preserve registers
lea Via1Int,a3 ; use the VIA1 interrupt dispatcher
*fall into* bra.s ServiceInt ; call primary interrupt dispatcher
;_______________________________________________________________________
;
; Routine: ServiceInt - Primary Interrupt Dispatcher
; Inputs: A3 - address of secondary interrupt dispatcher
; Stack contains saved 'IntRegs' with an interrupt stack
; frame below them.
; This routine is branched to (or fallen into), and will restore
; the saved 'IntRegs' and return from the stacked interrupt.
; Outputs: none
; Destroys: A0, A1, A2, D0, D1, D2
;
;
; Function: Provides a centralized handler for calling a secondary dispatcher.
; Creates a consistent environment for all secondary interrupt dispatchers,
; to allow them to easily decode the interrupt source and pass then on
; to other handlers. The interrupt environment is as follows. Registers
; A0-A3/D0-D3 are preserved.
; The secondary interrupt dispatcher will then be called, with a JSR, and
; may either return with an RTS when done, of JMP to another dispatcher to
; do more decoding of the interrupt, and then it can either RTS or JMP.
;
; When the interrupt processing has been completed, and control returns
; back to this routine, it will call any queued Deferred Tasks (if returning
; to level zero),restore the saved registers A0-A3/D0-D3, and return from the
; primary interrupt with an RTE instruction.
;
;_______________________________________________________________________
ServiceInt jsr (a3) ; call the secondary interrupt dispatcher
tst.l DTskQHdr ; see if any deferred tasks are queued
beq.s NoDTasks ; if none, don't need to run them
; IMPORTANT!! - following calculation depends on stack setup
; Must be changed if stack usage changed!
moveq.l #$07,d0 ; mask for int level in saved SR ($0700)
and.b IntRegsSize(sp),d0 ; test upper byte of saved SR
bne.s NoDTasks ; if not returning to level zero, don't run tasks
jsr vDisptch ; dispatch the deferred tasks
NoDTasks movem.l (sp)+,IntRegs ; restore registers
rte ; and return from the interrupt
;_______________________________________________________________________
;
; Routines: Via1Int - Secondary Interrupt Dispatcher
; Inputs: none
; Outputs: A1 - base address of the interrupting VIA
; Destroys: A0, A1, D0
;
; Function: Decodes and prioritizes VIA interrupts, locates a handler
; for the highest priority enable VIA interrupt source in the Via1DT
; or Via2DT as shown below. The handler is jumped to, and it will return
; to the primary interrupt handler when done.
;
;
; Via1DT -> (00) CA2 highest priority
; (04) CA1 |
; (08) shift reg |
; (0C) CB2 |
; (10) CB1 |
; (14) T2 Timer \|/
; (18) T1 Timer V
; (1C) spurious: no interrupt pending lowest priority
;
;_______________________________________________________________________
Via1Int movea.l VIA,a1 ; get VIA1 base address
moveq.l #$7F,d0 ; mask for interrupt pending bits (clr high bit)
and.b vIFR(a1),d0 ; get VIA interrupt pending flags
and.b vIER(a1),d0 ; only process enabled interrupts
add.w d0,d0 ; setup index into table of words
movea.w PrioritizeViaInts(d0.w),a0 ; get the dispatch table offset
movea.l (a0),a0 ; get routine address from table
jmp (a0) ; dispatch to routine
PrioritizeViaInts
dc.w Via1DT+(4*7) ; 0 0 0 0 0 0 0 no bits set
dc.w Via1DT+(4*0) ; 0 0 0 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 0 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 0 0 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 0 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 0 0 0 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 0 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 0 0 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 0 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 0 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*4) ; 0 0 1 0 0 0 0 bit 4 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 1 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 0 1 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 1 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 0 0 1 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 1 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 0 1 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 0 1 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 0 1 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*5) ; 0 1 0 0 0 0 0 bit 5 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 0 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 1 0 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 0 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 0 1 0 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 0 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 1 0 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 0 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 0 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*4) ; 0 1 1 0 0 0 0 bit 4 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 1 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 1 1 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 1 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 0 1 1 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 1 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 0 1 1 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 0 1 1 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 0 1 1 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*6) ; 1 0 0 0 0 0 0 bit 6 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 0 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 0 0 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 0 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 1 0 0 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 0 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 0 0 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 0 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 0 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*4) ; 1 0 1 0 0 0 0 bit 4 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 1 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 0 1 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 1 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 1 0 1 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 1 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 0 1 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 0 1 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 0 1 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*5) ; 1 1 0 0 0 0 0 bit 5 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 0 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 1 0 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 0 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 1 1 0 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 0 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 1 0 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 0 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 0 1 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*4) ; 1 1 1 0 0 0 0 bit 4 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 0 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 1 0 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 0 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 1 1 0 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 0 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 1 0 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 0 1 1 1 bit 0 is highest priority
dc.w Via1DT+(4*3) ; 1 1 1 1 0 0 0 bit 3 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 1 0 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 1 1 0 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 1 0 1 1 bit 0 is highest priority
dc.w Via1DT+(4*2) ; 1 1 1 1 1 0 0 bit 2 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 1 1 0 1 bit 0 is highest priority
dc.w Via1DT+(4*1) ; 1 1 1 1 1 1 0 bit 1 is highest priority
dc.w Via1DT+(4*0) ; 1 1 1 1 1 1 1 bit 0 is highest priority
;_______________________________________________________________________
;
; Routine: SccDecode 8530 SCC Interrupt Dispatcher
;
; All SCC interrupts: this interrupt dispatcher determines the actual
; interrupting source and dispatches through a table of secondary vectors
; maintained in the SYSCOM area. The table looks like this:
;
; SccDT -> (00) channel B: transmit buffer empty
; (04) channel B: external status (or mouse vertical interrupt)
; (08) channel B: receive character available
; (0C) channel B: special receive condition
; (10) channel A: transmit buffer empty
; (14) channel A: external status (or mouse horizontal interrupt)
; (18) channel A: receive character available
; (1C) channel A: special receive condition
;
; SccDT contains a long entry-point address for each of the eight primary
; interrupt routines corresponding to the eight primary interrupting sources.
;
; The two external status interrupts may be broken down into the following
; sources by the primary receiver:
;
; zero count (when the SCC baud rate generator is used as a timer)
; DCD (or mouse vertical/horizontal)
; sync/hunt (for synchronous serial modes only)
; CTS (external handshake in signal)
; Txunderrun/EOM (for synchronous serial modes only)
; Break/abort (interrupts when break(async)/abort(sync) begins and ends)
;
; A secondary dispatch is made for external/status interrupts through
; the external/status dispatch table:
;
; ExtStsDT -> (00) ext/sts B - non-mouse
; (04) unused (or mouse vertical interrupt)
; (08) ext/sts A - non-mouse
; (0C) unused (or mouse horizontal interrupt)
;
; A check is made to determine whether the mouse input (DCD) has changed
; from the last time: if so, the dispatch is made through the mouse
; vector, if not, thru the non-mouse vector. D0 contains the current
; status (read reg 0) and D1 the changed bits from the previous time
; an extenal/status interrupt was received; a reset ext/sts command is also given.
;
; The two special receive condition interrupts may also be further subdivided, but
; all subdivisions are directly related to serial data transfer and not the mice:
;
; end of frame (synchronous modes)
; CRC/framing error
; receiver overrun
; parity error
; all sent (asynchronous mode only)
;
; Each primary routine is entered with the processor priority masked, and with
; registers D0-D3 and A0-A3 available for use; A0 will point to SCC channel A/B
; control read address and A1 to SCC channel A/B control write address,
; depending upon which channel is interrupting:
;
; (READ ADDRESS) (WRITE ADDRESS)
;
; CHANNEL A/B DATA 4(A0) 4(A1)
;
; CHANNEL A/B CONTROL (A0) (A1)
;
; Each routine (except for external/status secondary routines) is responsible
; for clearing the source of the interrupt in the SCC, and for saving and
; restoring any additional A or D registers used.
;
; Routines must exit with an RTS rather than an RTE.
;
;
; The interrupt routine is selected by reading the SCC modified interrupt vector.
; The SCC selects the particular vector to supply according to a fixed priority:
;
; Receiver channel A (highest)
; Transmit channel A
; Ext/Status channel A
; Receiver channel B
; Transmit channel B
; Ext/Status channel B (lowest)
;
; The highest priority interrupt which is also enabled is selected by the SCC.
; Only processing one request at a time allows SccDecode to be re-entrant and service
; routines may lower the processor priority as soon as possible in order to
; process other pending interrupts.
;
; Written by: Bud Tribble 25-Mar-81
;
SccDecode MOVE.L SCCRd,A0 ; get SCC read address
MOVE.B (A0),D0 ; read to sync up SCC (just to be safe)
MOVE.L SCCWr,A1 ; get SCC channel B write control address
SccDecodeCommon
MOVE.B #2,(A1) ; point to SCC register 2, B channel
LEA SccDT,A2 ; point to dispatch table and delay
MOVEQ #$0E,D0 ; 'and mask' and extra delay
AND.B (A0),D0 ; read the modified interrupt vector
CMPI.B #8,D0 ; channel A interrupt?
BLT.S @GoLvl2 ; branch if for B <C914>
ADDQ #2,A0 ; adjust SCC addresses for port A
ADDQ #2,A1
@GoLvl2
ADD D0,D0 ; double vector for dispatch <C914>
MOVE.L 0(A2,D0.W),A2 ; get dispatch vector
JMP (A2) ; chain to service routine
;_______________________________________________________________________
;
; Routine: DTINSTALL
;
; Arguments: A0 (input) : address of deferred task queue element
; D0 (output): error code - 0 no error
; -2 invalid queue element
;
; Function: Installs a deferred task queue element into the deferred
; task queue pointed to by the low memory variable DTQueue.
;
; Format of the deferred task queue element is:
;
; DTLink Link to next queue element (pointer)
; DTType element ID (word = DTQType)
; DTFlags optional flags (word)
; DTAddr address of deferred task routine (pointer)
; DTParm optional A1 parameter (long)
; DTReservd reserved for future use (long)
;
; Registers Used: D0,A1, A0
;_______________________________________________________________________
DTINSTALL CMP.W #DTQType,DTType(A0) ; is it the proper type? <1.2>
BNE.S TypeErr ; return error if not
; now we jsr to the EnQueue routine to add the element to task queue.
; We jump directly thru trap vector for our specific machine to save time
; and avoid the trap dispatcher, which may be important for interrupt-time code.
; (deferred tasks tend to get installed in secondary interrupt handlers)
lowEnqueueByte EQU $16F
move.l a2,-(sp) ; save out a2
lea DTQueue,a1 ; get ptr to queue (SE--low-mem global)
move.l #(ToolTable+(4*lowEnqueueByte)), a2 ; calculate vector for Enqueue call
move.l (a2),a2 ; get addr of Enqueue from vector
jsr (a2) ; go Enqueue (on SE)
MOVEQ.L #noErr,D0 ; no errors
move.l (sp)+,a2 ; restore a2
RTS ; return to caller
TypeErr MOVEQ.L #VTypErr,D0 ; else flag the error
RTS ; and return with error code in D0 <1.2>
;______________________________________________________________________ <1.2>
;
; Dispatch routine for deferred tasks. This routine checks the deferred
; task queue and removes and executes all tasks found. Regs D0-D3
; and A0-A3 are saved prior to call.
;
; Bit test the flags to see if we were already executing a deferred task
; when the interrupt occurs. If so, then we should just return to finish up
; that task; don't start a new one. (Any tasks that have gotten queued
; during the interrupt will be caught when the current DT returns.)
;______________________________________________________________________
vDisptch BTST.B #INVBL,QFLAGS+VBLQUEUE ; doing VBL tasks?
BNE.S @Exit ; if so, keep deferring
BSET.B #InDTQ,DTQFlags ; already in dispatcher? (SE--lowmem check)
BEQ.S DspStart ; check the queue if not
@Exit RTS ; otherwise exit
DspLoop MOVEA.L D0,A0 ; else setup ptr for use
; now we jsr to the DeQueue routine to add the element to task queue.
; We jump thru the vectors on our specific machine to save time
; and avoid the trap dispatcher, which may be important for interrupt-time code.
lowDeQueuebyte EQU $16E
lea DTQueue,a1 ; get ptr to queue (SE--low-mem global)
move.l #(ToolTable+(4*lowDeQueuebyte)),a2 ; calc vector for Dequeue
move.l (a2),a2 ; get Dequeue addr from vector
jsr (a2) ; go Dequeue (on SE)
MOVEA.L DTAddr(A0),A2 ; get ptr to first task
MOVEA.L DTParm(A0),A1 ; get optional parameter
ANDI.W #$F8FF,SR ; enable all ints
JSR (A2) ; and go do task
DspStart ORI.W #HiIntMask,SR ; disable all ints
MOVE.L DTskQHdr,D0 ; get queue head (SE--lowmem)
BNE.S DspLoop ; loop if tasks exist
BCLR.b #InDTQ,DTQFlags ; clear indicator (SE--lowmem)
RTS ; and exit
endproc
;_______________________________________________________________________
; End of Patch code for:
;<2.7> Deferred Task Manager _DTInstall Trap, vDisptch
; EH Interrupt Handlers Lvl1Int, Lvl2Int, Lvl3Int
;_______________________________________________________________________
; ------------------------------------------------------------------------------------
;<<<END PATCH CODE>>> <- This is to make the end of this list easy to find with MPW.
;find /<<<END INSTALL CODE>>>/ "{active}" # Execute to find the next available change number.
;############################### END PATCH CODE ##############################################
;
;############################# PATCH INSTALL CODE ############################################
RAMSysInit PROC EXPORT
IMPORT SysBase,CutBack
Move.L D1,-(SP) ;save our handle
;############################# PATCH INSTALLS GO HERE ################################
; Initialize some new LowMems <5.9>
move.w #$0105,TimeViaDB; number of VIA accesses per millisecond <5.9>
; PMAB354 07Jan88 EMT Unimplemented Toolbox versions of 12 bisexual traps
INCLUDE 'ToolboxCastration.a'
; Install MapFBlock patch (P005,S118)
IMPORT MapFBPatch
LEA MapFBPatch,A0 ; install patch code
MOVE.L A0,jMapFBlock ;
; PA489 04May88 EMT Addition to PA419 - Remove Radius SetTrapAddress patch.
movem.l $F80078,d0/a0 ; hook contents
cmp.l #$55AAAA55,d0 ; sign of Zorro?
bne.s @notRadiusAcc ; if not the sign of AJH, go on
; If here, than a Radius Accellerator SE is installed, with ROM version <= 2.0
; Time to pull some teeth!
MOVEQ #$47, D0 ; SetTrapAddress #
_GetTrapAddress ; Get the address in A0
MOVE.L A0, $51C ; And stuff it back in the OS table.
@notRadiusAcc
; P014 TJ 09dec86 TJ WakeUp SonyQDUtil.a
IMPORT SonyWakeUp
MOVE.L #SONYVERLOC,A0
CMP.B #1,(A0) ; if sony driver is 1 then install patch
BNE.S @defer ; else don't install
LEA SonyWakeUp,A0 ; Point to Sony wakeup entry point
MOVE.L A0,$0246 ; ($246 == jWakeUp) Redirect Sony wakeup routine
@defer
; P015 12Dec86 EMT GetOSEvent OSEventMgr.a
InstOSTp GetOSEvent, $31 ; Replace GetOSEvent
; P015 12Dec86 EMT OSEventAvail OSEventMgr.a
InstOSTp OSEventAvail, $30 ; Replace OSEventAvail
; P015 12Dec86 EMT KbdDrvr kbd.a
MOVE.W KeyLast, KbdLast ; Move the global
CLR.W KeyLast ; Stop repeating
iADBAddr EQU -2
iDataAddr EQU iADBAddr-4
iCRAddr EQU iDataAddr-4
iOrigAddr EQU iCRAddr-1
iDeviceTy EQU iOrigAddr-1
iPBlock EQU iDeviceTy
iSPBlock EQU iCRAddr
iLocalData EQU iDeviceTy ; Just a stack frame
_CountADBs ; Count the number of ADB devices
MOVE.W D0, D2 ; Save it in D2
BEQ.S @DoneKInst ; Skip if there are none
LINK A6, #iLocalData
MOVEQ #2, D1 ; We're looking for keyboards
@KInstLoop
LEA iPBlock(A6), A0 ; the parameter block
MOVE.W D2, D0 ; the count
_GetIndADB ; Get the record
BMI.S @NextRec ; Skip if not valid
CMP.B iOrigAddr(A6), D1 ; Is this a keyboard?
BNE.S @NextRec ; Skip if not
IMPORT KbdDrvr
LEA KbdDrvr, A0 ; Get the address of my driver
MOVE.L A0, iCRAddr(A6) ; Put it in the parameter block
LEA iSPBlock(A6), A0 ; Point to the parameter block
_SetADBInfo ; Set it (ADB Address is still in D0)
@NextRec
SUBQ.W #1, D2 ; Decrement the count
BGT.S @KInstLoop ; Loop if >0
UNLK A6
@DoneKInst
; P019 C570 23Dec86 ABO VInstall atalk:lap.a
InstOSTp NewVInstall,$33 ; Replace VInstall
; P021 C491 08Dec86 DAF GetWVariant WindowMgr2.a:GetWVariant
InstToolTp GetWVariant,$0A ; install GetWVariant
; P022 C491 08Dec86 DAF GetCVariant ControlMgr1.a:GetCVariant
InstToolTp GetCVariant,$09 ; install GetCVariant
; PA061 C628 25feb87 bbm added new trap rGetResource.
InstToolTp NewrGetResource,$0C ; install rGetResource
; PMA314 25Nov87 EMT Patch GetResource to get MBDF instead of ROM override on Plus, SE
; PA081 03Mar87 SHF NewSCSICmd SCSIMgr.a:SCSICmd
; PMA211 20Jul87 SHF NewSCSI{Read,Write,RBlind,WBlind} SCSIMgr.a:SCSIRead, etc.
; PMAB466 13Apr88 JWK NewSCSIGet SCSIMgr.a:SCSIGet
MOVE.L SCSIGlobals,A1 ; pointer to SCSI globals
lea.l NewSCSIGet,a0 ; pointer to patch routine <PMAB466/JWK>
move.l a0,1*4(a1) ; SCSIGet = selector 1 <PMAB466/JWK>
LEA NewSCSICmd,A0 ; pointer to patch routine
MOVE.L A0,3*4(A1) ; SCSICmd = selector 3
LEA NewSCSIRead,A0 ; pointer to patch routine
MOVE.L A0,5*4(A1) ; SCSIRead = selector 5
LEA NewSCSIWrite,A0 ; pointer to patch routine
MOVE.L A0,6*4(A1) ; SCSIWrite = selector 6
LEA NewSCSIRBlind,A0 ; pointer to patch routine
MOVE.L A0,8*4(A1) ; SCSIWrite = selector 8
LEA QuantumWBlindSE,A0 ; new blind write for quantum 7.9 fix <50> djw
MOVE.L A0,9*4(A1) ; SCSIWBlind = selector 9
; PMAB295 20Oct87 SHF SCSISelect SCSIMgr.a:SCSISelect
ROM76Load EQU $404058 ; Mac SE SCSILoad <PMAB295>
ROM76Select EQU $41A2C4 ; Select code <PMAB295>
BSR.S @ClearBus ; clear up bus problems first <PMAB295>
MOVE.L SCSIGlobals,A0 ; pointer to SCSIMgr variables <PMAB295>
MOVE.L 2*4(A0),-(SP) ; save old Select vector <PMAB295>
LEA @Sel76Patch,A1 ; pointer to my patch routine <PMAB295>
MOVE.L A1,2*4(A0) ; patch out the Select vector <PMAB295>
MOVE.B #$FE,d0 ; try all drivers but 0 (int.) <PMAB295>
JSR ROM76Load ; take the leap of faith <PMAB295>
MOVE.L SCSIGlobals,A0 ; pointer to SCSIMgr variables <PMAB295>
MOVE.L (SP)+,2*4(a0) ; restore the old Select vector <PMAB295>
BSR.S @ClearBus ; clear up remaining problems <PMAB295>
BRA.S @SCSIDone
@ClearBus
CLR.W -(SP) ; prepare for return value <PMAB295>
_SCSIStat ; get current SCSI bus status <PMAB295>
AND.W #aBSY+aSEL,(SP) ; test BSY&SEL, leave word on stack <PMAB329/10Dec87/JWK>
BEQ.S @ClearRts ; no BSY or SEL, so return <PMAB329/10Dec87/JWK>
@IsBusFloating
AND.W #aSEL,(SP) ; test SEL: floating SCSI bus ? <PMAB329/10Dec87/JWK>
BNE.S @ClearRts ; BSY&SEL true - nothing attached <PMAB329/10Dec87/JWK>
PEA Scratch8 ; address for status byte <PMAB295>
PEA Scratch8+2 ; address for message byte <PMAB295>
MOVE.L #OneSecTicks*5,-(SP) ; wait up to five seconds <PMAB295>
_SCSIComplete ; try to get to Bus Free state <PMAB295>
@ClearRts
ADDQ.L #2,SP ; pop off return code <PMAB295>
RTS
@Sel76Patch
MOVEQ.L #0,D0 ; clear upper bits <PMAB295>
MOVE.W 8(A6),D0 ; get the target's ID <PMAB295>
MOVE.W #25,d6 ; select timeout (ms) <PMAB295>
JMP ROM76Select ; go to rest of the ROM routine <PMAB295>
@SCSIDone
; PAB087 06Mar87 CSL JCrsrTask patch
LEA JCrsrTask,A0
IMPORT CrsrPtch
LEA CrsrPtch,A1
MOVE.L A1,(A0) ; install the TrimMeasure hook
;------------------------------------------------------------------------------
; PMA097 <FJL> -- Back-patch hierarchical menus
;------------------------------------------------------------------------------
; PMA311 24Nov87 EMT Install Menu Manager using 'ptchInstall' method.
InstToolTp FindWindow,$12C ; (#PMA100) <10Mar87 DAF>
InstToolTp InitWindows,$112 ; (#PMA100) <10Mar87 DAF>
; PABM150
InstOSTp mySysEnvirons,$90
; PA182 21May87 CSL DiskSelect SonyQDUtil.a:DiskSelect
IMPORT RDiskSelect
MOVE.L #SONYVERLOC,A0
CMP.B #1,(A0) ; if sony driver is 1 then install patch
BNE.S @defer2 ; else don't install
LEA RDiskSelect,A0
LEA JDiskSel,A1
Move.L A0,(A1)
@defer2
; PMA207 17Jul87 EHB PackBits ; bitmaps.a
InstToolTp NewPackBits,$CF ; patch PackBits
;
; PB235 -- Install FClose patches
;
FCloseInst
import saveDtrmV3,DtrmV3Patch,svFlushCache,FlCachePatch,BTClosePatch,BTFlushPatch
lea saveDtrmV3,a0 ; Save original address of DtrmV3
move.l jDtrmV3,(a0) ; ...so we can call it
LEA DtrmV3Patch,A0 ; install patch code
MOVE.L A0,jDtrmV3 ;
lea svFlushCache,a0 ; Save original address of FlushCache
move.l jFlushCache,(a0) ; ...so we can call it
lea FlCachePatch,a0 ; Install our patch
move.l a0,jFlushCache
lea BTClosePatch,a0 ; Install BTClose vector
move.l a0,jBTClose
lea BTFlushPatch,a0 ; Install BTFlush vector
move.l a0,jBTFlush
;
; PB235 -- End of FClose patch install
;
; PM244 -- Install Unmount patch
InstOSTp UnmountPatch,$0E ; <24Aug87>
; PMAB241 25Aug87 RDC - install BadTrap patch
IMPORT NewBadTrap
InstToolTp NewBadTrap,$1FF ; replace Debugger trap $A9FF
InstToolTp NewBadTrap,$3FF ; replace Debugger trap $ABFF
; PMAB301 16Nov87 ABO ATP SendRequest
MOVE.L AGBHandle, A0 ; <9> PWD 3/21/90 Check to see if AGBHandle is already
CMP.L #-1, A0 ; <9> allocated, if so, skip the _NewHandle
BNE.S @ATInstalled ; <9>
MOVEQ #AGBSize,D0 ; D0 = size of block
_NewHandle ,SYS,CLEAR ; Get it
BNE.S @NoATPPatch ; Error if can't
MOVE.L A0,AGBHandle ; Set in lowmem
@ATInstalled ; <9>
MOVE.L (A0),A0 ; A0 -> AppleTalk Global Block
LEA ATPPatch,A1 ; A1 -> patch to SendRequest
MOVE.L A1,ATPHook(A0) ; Set in patch hook
@NoATPPatch
; <1.7> 2Feb89 CCH Added Gestalt.
; <4.5> <08/19/89 pke> Moved this up here so other 'ptch' files can use Gestalt
; (e.g TextEdit needs this for 6.0.4 scripts builds and for 7.0)
PtchInst 5
; PMAB372 26Jan88 djw Install async serial driver patch for DTR bug ($BE is assigned vector)
; <51> 17Dec90 eh install new version number for driver
InstOSTp asyncPatch,$BE
SERDVersion equ 5
; install new version number
move.l #5*4,d0 ; first serial DCE is 5th entry in Utbl
moveq #4-1,d1 ; index through 4 dce's (adjusted for dbra)
@next movea.l UTableBase,a0 ; get ptr to the unit table
movea.l 0(a0,d0.w),a0 ; get DCE handle
movea.l (a0),a0 ; get DCE ptr
move.w #SERDVersion,dCtlQueue(a0) ; post new version
addq #4,d0 ; get next DCE
dbra d1,@next
;
; PA511 -- Install code for UpdAltMDB patch
;
IMPORT svExtBTFile,MyExtBTF
lea svExtBTFile,a0 ; Point to save of ROM routine
move.l jExtBTFile,(a0) ; Save addr of ROM routine
lea MyExtBTF,a0 ; Point to the patch
move.l a0,jExtBTFile ; Install ourselves in the vector
;_____________________________________________________________________________
; PP332
; Install Cache control trap
;_____________________________________________________________________________
InstOSTp CacheTrap,$74 ; install the HFS RAM disk cache control trap
;_____________________________________________________________________________
; End of Cache control trap installation
;_____________________________________________________________________________
; P012 C481 04dec86 CRC SetFractEnable fontmgr.a:SetFractEnable
InstToolTpNum $419E42,$14 ; set up SetFractEnable
IF NOT hasSplineFonts THEN
InstToolTp FMSwapFont,$101 ; replace FMSwapFont
InstToolTp NewStdTxMeas,$ED ; replace StdTxMeas
ENDIF
; S497 7June88 med Changed Script Manager to ptch resource
PtchInst 4
; Script Manager 7.0 extensions (must be after PtchInst 4 !!) to be included for 6.0.6 builds.
IF installScriptMgrPtch27 THEN ; <4.8> <16>
PtchInst 27 ; <4.8> Must load after ptch 4 !
ENDIF ; <4.8>
;______________________________________________________________________
; Start of Initialization code for:
;<2.7> Deferred Task Manager _DTInstall Trap, vDisptch
; EH Interrupt Handlers Lvl1Int, Lvl2Int, Lvl3Int
;
; InitIntHandler: Initialize exception dispatch tables --
; VIA (#1) interrupts -- 8 vectors; level 1 interrupts on all Mac, Mac++
; SCC interrupts -- 8 vectors; level 2 on Mac, Mac++
; 68xxx exception vectors -- low mem dispatch table
; deferred task vectors -- low mem dispatch table
;
;______________________________________________________________________
import DTInstall
import vDisptch
import level1Int
import level2Int
import level3Int
; patch in the addr for Deferred Task Handler
lea vDisptch ,a0 ; stuff the vector for the handler
move.l a0, jDisptch
lea DTInstall,A0 ; move to A0 for SetTrapAddress
move.l a0,jDTInstall ; stuff that extra vector
move.w #$A082,D0 ; get trap number
_SetTrapAddress NewOS ; install _DTInstall
;
; initialize the queue header, which is in low mem
;
lea DTQueue,a0 ; SE queue, low-mem global
clr.w (a0)+ ; Qflags
clr.l (a0)+ ; QHead
clr.l (a0) ; QTail
; and finally replace the interrupt autovectors (turn of interrupts while
; we muck around with their handler vectors)
move.w SR, -(sp)
ori.w #HiIntMask,SR ; disable all ints
lea AutoInt1,a2 ; point to main vectors in low mem
lea Level1Int,a0 ; level 1 interrupt handler
move.l a0,(a2)+ ;
lea Level2Int,a0 ; level 2 interrupt handler
move.l a0,(a2)+
lea Level3Int,a0 ; level 3 interrupt handler
move.l a0,(a2)+ ;
move.w (sp)+, SR ; re-enable interrupts
;_______________________________________________________________________
; End of Initialization code for:
;<2.7> Deferred Task Manager _DTInstall Trap, vDisptch
; EH Interrupt Handlers Lvl1Int, Lvl2Int, Lvl3Int
;_______________________________________________________________________
;<<<END INSTALL CODE>>> <- This is to make the end of this list easy to find with MPW.
;############################### END INSTALL CODE ####################################
;
;############################# PATCHES CUT BACK CODE #################################
;
LEA RAMSysInit,A1 ; cut back to here . . . <23Apr86 LAK>
LEA SysBase,A0 ; start of patch code <23Apr86 LAK>
Sub.L A0,A1 ; size of patch code <23Apr86 LAK>
Move.L A1,D0 ; <23Apr86 LAK>
Move.L (SP)+,A0 ; restore the handle passed by SysPatch <23Apr86 LAK>
BRA CutBack ; cut us back -> <23Apr86 LAK>
;########################### END PATCHES CUT BACK CODE ################################
UsesPtchInst ; Patch Install code ;<2.3-4april89-CEL>
End