Home | History | Annotate | Line # | Download | only in mac68k
      1 /*	$NetBSD: pramasm.s,v 1.10 2022/05/23 19:52:34 andvar Exp $	*/
      2 
      3 /*
      4  * RTC toolkit version 1.08b, copyright 1995, erik vogan
      5  *
      6  * All rights and privledges to this code hereby donated
      7  * to the ALICE group for use in NetBSD.  see the copyright
      8  * below for more info...
      9  */
     10 /*
     11  * Copyright (c) 1995 Erik Vogan
     12  * All rights reserved.
     13  *
     14  * This code is derived from software contributed to the Alice Group
     15  * by Erik Vogan.
     16  *
     17  * Redistribution and use in source and binary forms, with or without
     18  * modification, are permitted provided that the following conditions
     19  * are met:
     20  * 1. Redistributions of source code must retain the above copyright
     21  *    notice, this list of conditions and the following disclaimer.
     22  * 2. Redistributions in binary form must reproduce the above copyright
     23  *    notice, this list of conditions and the following disclaimer in the
     24  *    documentation and/or other materials provided with the distribution.
     25  * 3. All advertising materials mentioning features or use of this software
     26  *    must display the following acknowledgement:
     27  *	This product includes software developed by the Alice Group.
     28  * 4. The names of the Alice Group or any of its members may not be used
     29  *    to endorse or promote products derived from this software without
     30  *    specific prior written permission.
     31  *
     32  * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
     33  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     34  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     35  * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
     36  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     37  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     38  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     39  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     40  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     41  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     42  */
     43 
     44 /*
     45  *  The following are the C interface functions to RTC access functions
     46  * that are defined later in this file.
     47  */
     48 
     49 #include "opt_adb.h"
     50 
     51 #include <m68k/asm.h>
     52 
     53 #ifdef MRG_ADB
     54 /*
     55  * These functions are NOT defined at all if we are not using
     56  * the MRG method of accessing the ADB/PRAM/RTC.
     57  */
     58 
     59 	.text
     60 
     61 	.even
     62 ENTRY(readPram)
     63 	link	%a6,#-4		|  create a little home for ourselves
     64 	.word	0xa03f		|  _InitUtil to read PRam
     65 	moveml	%d1/%a1,%sp@-
     66 	moveq	#0,%d0		|  zero out length register
     67 	moveb	%a6@(19),%d0	|  move the length byte in
     68 	moveq	#0,%d1		|  zero out location
     69 	moveb	%a6@(15),%d1	|  now get out PRam location
     70 	lea	_C_LABEL(SysParam),%a1	|  start of PRam data
     71 	movel	%a6@(8),%a0	|  get our data address
     72 _readPramAgain:
     73 	subql	#1,%d0
     74 	bcs	_readPramDone	|  see if we are through
     75 	moveb	%a1@(%d1),%a0@+	|  transfer byte
     76 	addql	#1,%d1		|  next byte
     77 	jmp	_readPramAgain	|  do it again
     78 _readPramDone:
     79 	clrw	%d0
     80 	moveml	%sp@+,%d1/%a1
     81 	unlk	%a6 		|  clean up after ourselves
     82 	rts			|  and return to caller
     83 
     84 
     85 ENTRY(writePram)
     86 	link	%a6,#-4		|  create a little home for ourselves
     87 	.word	0xa03f		|  _InitUtil to read PRam in the case it hasn't been read yet
     88 	moveml	%d1/%a1,%sp@-
     89 	moveq	#0,%d0		|  zero out length register
     90 	moveb	%a6@(19),%d0	|  move the length byte in
     91 	moveq	#0,%d1		|  zero out location
     92 	moveb	%a6@(15),%d1	|  now get out PRam location
     93 	lea	_C_LABEL(SysParam),%a1	|  start of PRam data
     94 	movel	%a6@(8),%a0	|  get our data address
     95 _writePramAgain:
     96 	subql	#1,%d0
     97 	bcs	_writePramDone	|  see if we are through
     98 	cmpil	#0x14,%d1	|  check for end of _SysParam
     99 	bcc	_writePramDone	|  do not write if beyond end
    100 	moveb	%a0@+,%a1@(%d1)	|  transfer byte
    101 	addql	#1,%d1		|  next byte
    102 	jmp	_writePramAgain |  do it again
    103 _writePramDone:
    104 	.word	0xa038		|  writeParam
    105 	moveml	%sp@+,%d1/%a1
    106 	unlk	%a6 		|  clean up after ourselves
    107 	rts			|  and return to caller
    108 
    109 
    110 ENTRY(readExtPram)
    111 	link	%a6,#-4		|  create a little home for ourselves
    112 	moveq	#0,%d0		|  zero out our future command register
    113 	moveb	%a6@(19),%d0	|  move the length byte in
    114 	swap	%d0		|  and make that the MSW
    115 	moveb	%a6@(15),%d0	|  now get out PRAM location
    116 	movel	%a6@(8),%a0	|  get our data address
    117 	.word	0xa051		|  and go read the data
    118 	unlk	%a6 		|  clean up after ourselves
    119 	rts			|  and return to caller
    120 
    121 ENTRY(writeExtPram)
    122 	link	%a6,#-4		|  create a little home for ourselves
    123 	moveq	#0,%d0		|  zero out our future command register
    124 	moveb	%a6@(19),%d0	|  move the length byte in
    125 	swap	%d0		|  and make that the MSW
    126 	moveb	%a6@(15),%d0	|  now get out PRAM location
    127 	movel	%a6@(8),%a0	|  get our data address
    128 	.word	0xa052		|  and go write the data
    129 	unlk	%a6 		|  clean up after ourselves
    130 	rts			|  and return to caller
    131 
    132 ENTRY(getPramTime)
    133 	link	%a6,#-4		|  create a little home for ourselves
    134 	.word	0xa03f		|  call the routine to read the time (InitUtil)
    135 	movel	_C_LABEL(Time),%d0
    136 	unlk	%a6		|  clean up after ourselves
    137 	rts			|  and return to caller
    138 
    139 ENTRY(setPramTime)
    140 	link	%a6,#-4		|  create a little home for ourselves
    141 	movel	%a6@(8),%d0	|  get the passed in long (seconds since 1904)
    142 	.word	0xa03a		|  call the routine to write the time
    143 	unlk	%a6		|  clean up after ourselves
    144 	rts			|  and return to caller
    145 
    146 #else
    147 /* The following routines are the hardware specific routines for the
    148  * machines that use the II-like method to access the PRAM, and are only
    149  * defined when the MRG method is not used to access the PRAM.
    150  */
    151 
    152 /*
    153  *  The following are the C interface functions to RTC access functions
    154  * that are defined later in this file.
    155  */
    156 
    157 	.text
    158 
    159 	.even
    160 ENTRY(readPramII)
    161 	link	%a6,#-4		|  create a little home for ourselves
    162 	moveq	#0,%d0		|  zero out our future command register
    163 	moveb	%a6@(19),%d0	|  move the length byte in
    164 	swap	%d0		|  and make that the MSW
    165 	moveb	%a6@(15),%d0	|  now get out PRAM location
    166 	oriw	#0x0100,%d0	|  and set up for non-extended read
    167 	movel	%a6@(8),%a0	|  get our data address
    168 	jbsr	_C_LABEL(PRAMacc)	|  and go read the data
    169 	unlk	%a6		|  clean up after ourselves
    170 	rts			|  and return to caller
    171 
    172 ENTRY(writePramII)
    173 	link	%a6,#-4		|  create a little home for ourselves
    174 	moveq	#0,%d0		|  zero out our future command register
    175 	moveb	%a6@(19),%d0	|  move the length byte in
    176 	swap	%d0		|  and make that the MSW
    177 	moveb	%a6@(15),%d0	|  now get out PRAM location
    178 	nop			|  and set up for non-extended write
    179 	movel	%a6@(8),%a0	|  get our data address
    180 	jbsr	_C_LABEL(PRAMacc)	|  and go write the data
    181 	unlk	%a6		|  clean up after ourselves
    182 	rts			|  and return to caller
    183 
    184 ENTRY(readExtPramII)
    185 	link	%a6,#-4		|  create a little home for ourselves
    186 	moveq	#0,%d0		|  zero out our future command register
    187 	moveb	%a6@(19),%d0	|  move the length byte in
    188 	swap	%d0		|  and make that the MSW
    189 	moveb	%a6@(15),%d0	|  now get out PRAM location
    190 	oriw	#0x0300,%d0	|  and set up for extended read
    191 	movel	%a6@(8),%a0	|  get our data address
    192 	jbsr	_C_LABEL(PRAMacc)	|  and go read the data
    193 	unlk	%a6		|  clean up after ourselves
    194 	rts			|  and return to caller
    195 
    196 ENTRY(writeExtPramII)
    197 	link	%a6,#-4		|  create a little home for ourselves
    198 	moveq	#0,%d0		|  zero out our future command register
    199 	moveb	%a6@(19),%d0	|  move the length byte in
    200 	swap	%d0		|  and make that the MSW
    201 	moveb	%a6@(15),%d0	|  now get out PRAM location
    202 	oriw	#0x0200,%d0	|  and set up for extended write
    203 	movel	%a6@(8),%a0	|  get our data address
    204 	jbsr	_C_LABEL(PRAMacc)	|  and go write the data
    205 	unlk	%a6		|  clean up after ourselves
    206 	rts			|  and return to caller
    207 
    208 ENTRY(getPramTimeII)
    209 	link	%a6,#-4		|  create a little home for ourselves
    210 	jbsr	_C_LABEL(readClock)	|  call the routine to read the time
    211 	unlk	%a6		|  clean up after ourselves
    212 	rts			|  and return to caller
    213 
    214 ENTRY(setPramTimeII)
    215 	link	%a6,#-4		|  create a little home for ourselves
    216 	movel	%a6@(8),%d0	|  get the passed in long (seconds since 1904)
    217 	jbsr	_C_LABEL(writeClock)	|  call the routine to write the time
    218 	unlk	%a6		|  clean up after ourselves
    219 	rts			|  and return to caller
    220 
    221 /*
    222  *  The following are the RTC access functions used by the interface
    223  * routines, above.
    224  */
    225 
    226 ENTRY_NOPROFILE(readClock)
    227 	moveml	#0x7cc0,%sp@-	| store off the regs we need
    228 	moveq	#00,%d0		| zero out our result reg
    229 readagan:
    230 	moveq	#00,%d5		| and our temp result reg
    231 	moveq	#03,%d4		| set our count down reg to 4
    232 	movel	#0x00000081,%d1	| read sec byte 0 first
    233 getSecb:
    234 	bsr	_C_LABEL(Transfer)	| get that byte
    235 	rorl	#8,%d5		| shift our time to the right
    236 	swap	%d1		| we want to access our new data
    237 	moveb	%d1,%d5		| move that byte to the spot we vacated
    238 	swap	%d1		| return our PRAM command to orig. config
    239 	addqb	#4,%d1		| increment to the next sec byte
    240 	dbf	%d4,getSecb	| any more bytes to get ?
    241 	cmpl	%d5,%d0		| same secs value we as we just got ?
    242 	beq	gotTime		| we got a good time value
    243 	movel	%d5,%d0		| copy our current time to the compare reg
    244 	bra	readagan	| read the time again
    245 gotTime:
    246 	rorl	#8,%d0		| make that last shift to correctly order
    247 				|  time bytes!!!
    248 	movel	#0x00d50035,%d1	| we have to set the write protect bit
    249 				| so the clock doesn't run down !
    250 	bsr	_C_LABEL(Transfer)	| (so sezs Apple...)
    251 	moveml	%sp@+,#0x033e	| restore our regs
    252 	rts			| and return to caller
    253 
    254 ENTRY_NOPROFILE(writeClock)
    255 	moveml	#0x78c0,%sp@-	| store off the regs we need
    256 	moveq	#03,%d4		| set our count down reg to 4
    257 	movel	#0x00550035,%d1	| de-write-protect the PRAM
    258 	bsr	_C_LABEL(Transfer)	| so we can set our value
    259 	moveq	#1,%d1		| write sec byte 0 first
    260 putSecb:
    261 	swap	%d1		| we want access to data byte of command
    262 	moveb	%d0,%d1		| set our first secs byte
    263 	swap	%d1		| and return command to orig. config
    264 	bsr	_C_LABEL(Transfer)	| write that byte
    265 	rorl	#8,%d0		| shift our time to the right
    266 	addqb	#4,%d1		| increment to the next sec byte
    267 	dbf	%d4,putSecb	| any more bytes to put ?
    268 	movel	#0x00d50035,%d1	| we have to set the write protect bit
    269 				| so the clock doesn't run down !
    270 	bsr	_C_LABEL(Transfer)	| (so sezs Apple...)
    271 	moveml	%sp@+,#0x031e	| restore our regs
    272 	rts			| and return to caller
    273 
    274 ENTRY_NOPROFILE(PRAMacc)
    275 	moveml	#0xf8c0,%sp@-	| store off the regs we'll use
    276 	moveq	#00,%d3		| zero out our command reg
    277 	moveq	#00,%d4		| zero out our count reg too
    278 	swap	%d0		| we want the length byte
    279 	movew	%d0,%d4		| copy length byte to our counter reg
    280 	swap	%d0		| and return command reg to prior state
    281 	subqb	#1,%d4		| predecrement counter for use w/ DBF
    282 	movew	%d0,%d2		| copy command to %d2
    283 	rorw	#8,%d2		| rotate copy to examine flags
    284 	roxrw	#1,%d2		| read/write bit out of param.
    285 	roxlb	#1,%d3		| and into command reg
    286 	tstb	%d3		| was it read (1) or write (0) ?
    287 	bne	NoWrit		| go around de-write protect logic
    288 	movel	#0x00550035,%d1	| clear write protect bit of PRAM
    289 				| (we really only need to zero the high
    290 				|  bit, but other patterns don't work! )
    291 	moveml	#0x3000,%sp@-	| store off the regs that'll change
    292 	bsr	_C_LABEL(Transfer)	| and go de-write protect RTC
    293 	moveml	%sp@+,#0x000c	| reclaim our reg values
    294 NoWrit:
    295 	andib	#1,%d2		| isolate the extended command bit
    296 	beq	oldPRAM		| it's zero, so do old PRAM style access
    297 NuPRAM:
    298 	moveb	%d0,%d2		| reget our PRAM location
    299 	lslw	#4,%d3		| insert our template blanks
    300 	moveq	#2,%d1		| set bit counter for 3 cycles
    301 threebit:
    302 	roxlb	#1,%d2		| rotate address bit from %d2
    303 	roxlw	#1,%d3		| and into command in %d3
    304 	dbf	%d1,threebit	| until we've done bits 7-5
    305 	lslw	#1,%d3		| and add a bit spacer
    306 	moveq	#4,%d1		| ok, 5 bits to go...
    307 fivebit:
    308 	roxlb	#1,%d2		| another addr bit out of %d2
    309 	roxlw	#1,%d3		| and into command template in %d3
    310 	dbf	%d1,fivebit	| til we've done bit 4-0
    311 	lslw	#2,%d3		| more bit magic
    312 	oriw	#0x3880,%d3	| set extended command bits
    313 	bra	Loaddata	| go load the rest of command for xfer rtn
    314 oldPRAM:
    315 	moveb	%d0,%d2		| reget our PRAM location
    316 	lslb	#1,%d3		| add a template blank (bit)
    317 	rolb	#4,%d2		| get low nibble of PRAM loc ready
    318 	moveq	#3,%d1		| set our bit counter for 4 cycles
    319 fourbit:
    320 	roxlb	#1,%d2		| bit out of PRAM loc
    321 	roxlb	#1,%d3		| and bit into PRAM command
    322 	dbf	%d1,fourbit	| until we've done the low nibble
    323 	lslb	#2,%d3		| bump bits to type of command byte
    324 	orib	#0x41,%d3	| set command bits (for access to $0-F!)
    325 	btst	#4,%d2		| change to access $10-13 ?
    326 	beq	Loaddata	| nope, should stay the way it is
    327 	andib	#0x8F,%d3	| clear bits 4-6 of current command
    328 	orib	#0x20,%d3	| and set bit 5 (now accesses $10-13)
    329 Loaddata:
    330 	moveb	%a0@,%d1	| get our (data/dummy) byte into %d1
    331 	swap	%d1		| move (data/dummy) byte to MSW
    332 	movew	%d3,%d1		| now move command into %d1
    333 tagain:
    334 	bsr	_C_LABEL(Transfer)	| now execute that command
    335 	swap	%d1		| we want access to (data/dummy) byte
    336 	moveb	%d1,%a0@+	| move (data/dummy) byte back to %a0,
    337 	moveb	%a0@,%d1	| NEXT VICTIM!!
    338 	swap	%d1		| now we want to tweak the command
    339 	addqw	#4,%d1		| increment our memory addr by 1 (this even
    340 				| works if we want to dump across 32 byte
    341 				| boundaries for an extended command!!!
    342 				| thanks to the oriw #$3880 above !!!)
    343 	dbf	%d4,tagain	| repeat until we've got all we want
    344 	movel	#0x00d50035,%d1	| remember that command to write the wp byte ?
    345 				| set the high bit in the wp reg (Apple sezs
    346 				| this way the battery won't wear down !! )
    347 	bsr	_C_LABEL(Transfer)	| so we'll play by the rules
    348 	moveml	%sp@+,#0x031f	| restore all our registers
    349 	rts			| and return to our gracious caller
    350 
    351 ENTRY_NOPROFILE(Transfer)
    352 	movew	%sr,%sp@-	| store the SR (we'll change it!)
    353 	oriw	#0x0700,%sr	| disable all interrupts
    354 	moveal	_C_LABEL(Via1Base),%a1	| move VIA1 addr in reference reg
    355 	moveq	#0,%d2		| zero out %d2 (it'll hold VIA1 reg B contents)
    356 	moveb	%a1@,%d2	| and get VIA1 reg B contents
    357 	andib	#0xF8,%d2	| don't touch any but RTC bits
    358 				| (and zero all those)
    359 	movew	%d1,%d3		| we want to manipulate our command
    360 	andiw	#0xFF00,%d3	| zero the LSB
    361 	beq	oldPRAMc	| do an old PRAM style command
    362 xPRAMc:
    363 	rorw	#8,%d1		| swap the command bytes (1st byte of 2)
    364 	bsr	writebyte	| and write the command byte
    365 	rorw	#8,%d1		| swap the command bytes again (2nd byte of 2)
    366 	bsr	writebyte	| write that byte to RTC too
    367 	moveq	#0x1F,%d3	| r/w bit is $F for an extended command
    368 				| (but command is swapped to MSW!! so add $10)
    369 	bra	Rwbrnch		| go figure out if it's a read or a write cmd
    370 oldPRAMc:
    371 	bsr	writebyte	| only one byte for an old PRAM command
    372 	moveq	#0x17,%d3	| r/w bit is $7 for and old PRAM command
    373 				| ( command is swapped to MSW, add $10)
    374 Rwbrnch:
    375 	swap	%d1		| better get that (data/dummy) byte ready
    376 	btst	%d3,%d1		| test bit no. %d3 of reg %d1 (read or write ?)
    377 	beq	Wtrue		| 0 = write, 1 = read (branch on write)
    378 Rtrue:
    379 	bsr	readbyte	| read a byte from the RTC
    380 	bra	Cleanup		| and call mom to clean up after us
    381 Wtrue:
    382 	bsr	writebyte	| write the data to the RTC
    383 Cleanup:
    384 	swap	%d1		| move command to LSW again
    385 	bset	#2,%a1@		| bring the RTC enable line high (end of xfer)
    386 	movew	%sp@+,%sr	| restore prior interrupt status
    387 	rts			| and return to caller
    388 
    389 writebyte:
    390 	moveq	#7,%d3		| set our bit counter to 8
    391 wagain:
    392 	lsrb	#1,%d2		| ditch the old data channel value
    393 	roxlb	#1,%d1		| and move a new value to X
    394 	roxlb	#1,%d2		| now move value from X to data channel
    395 	moveb	%d2,%a1@	| set our VIA1 reg B contents to match
    396 	bset	#1,%a1@		| and finish strobing the clock line
    397 	dbf	%d3,wagain	| do this until we've sent a whole byte
    398 	lsrb	#1,%d2		| ditch the data channel value one last time
    399 	roxlb	#1,%d1		| get rid of the extra X bit we've carried
    400 	lslb	#1,%d2		| and restore %d2 to prior status
    401 	rts			| return to caller
    402 
    403 readbyte:
    404 	moveq	#7,%d3		| set our bit counter to 8
    405 	bclr	#0,%a1@(0x0400)	| set VIA1 reg B data line to input
    406 ragain:
    407 	bclr	#1,%a1@		| strobe the clock line to make
    408 	bset	#1,%a1@		| the data valid
    409 	moveb	%a1@,%d2	| and get out data byte
    410 	lsrb	#1,%d2		| get the data channel value to X
    411 	roxlb	#1,%d1		| and move X to data byte
    412 	dbf	%d3,ragain	| do this until we've received a whole byte
    413 	bset	#0,%a1@(0x0400)	| and return RTC data line to output
    414 	rts			| return to caller
    415 
    416 #endif /* MRG_ADB */
    417 
    418