| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 | 2 | |MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP | 
 | 3 | |M68000 Hi-Performance Microprocessor Division | 
 | 4 | |M68060 Software Package | 
 | 5 | |Production Release P1.00 -- October 10, 1994 | 
 | 6 | | | 
 | 7 | |M68060 Software Package Copyright © 1993, 1994 Motorola Inc.  All rights reserved. | 
 | 8 | | | 
 | 9 | |THE SOFTWARE is provided on an "AS IS" basis and without warranty. | 
 | 10 | |To the maximum extent permitted by applicable law, | 
 | 11 | |MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, | 
 | 12 | |INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | 
 | 13 | |and any warranty against infringement with regard to the SOFTWARE | 
 | 14 | |(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials. | 
 | 15 | | | 
 | 16 | |To the maximum extent permitted by applicable law, | 
 | 17 | |IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER | 
 | 18 | |(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, | 
 | 19 | |BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) | 
 | 20 | |ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. | 
 | 21 | |Motorola assumes no responsibility for the maintenance and support of the SOFTWARE. | 
 | 22 | | | 
 | 23 | |You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE | 
 | 24 | |so long as this entire notice is retained without alteration in any modified and/or | 
 | 25 | |redistributed versions, and that such modified versions are clearly identified as such. | 
 | 26 | |No licenses are granted by implication, estoppel or otherwise under any patents | 
 | 27 | |or trademarks of Motorola, Inc. | 
 | 28 | |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
 | 29 | | os.s | 
 | 30 | | | 
 | 31 | | This file contains: | 
 | 32 | |	- example "Call-Out"s required by both the ISP and FPSP. | 
 | 33 | | | 
 | 34 |  | 
 | 35 | #include <linux/linkage.h> | 
 | 36 |  | 
 | 37 | |################################ | 
 | 38 | | EXAMPLE CALL-OUTS		# | 
 | 39 | |				# | 
 | 40 | | _060_dmem_write()		# | 
 | 41 | | _060_dmem_read()		# | 
 | 42 | | _060_imem_read()		# | 
 | 43 | | _060_dmem_read_byte()		# | 
 | 44 | | _060_dmem_read_word()		# | 
 | 45 | | _060_dmem_read_long()		# | 
 | 46 | | _060_imem_read_word()		# | 
 | 47 | | _060_imem_read_long()		# | 
 | 48 | | _060_dmem_write_byte()	# | 
 | 49 | | _060_dmem_write_word()	# | 
 | 50 | | _060_dmem_write_long()	# | 
 | 51 | |				# | 
 | 52 | | _060_real_trace()		# | 
 | 53 | | _060_real_access()		# | 
 | 54 | |################################ | 
 | 55 |  | 
 | 56 | | | 
 | 57 | | Each IO routine checks to see if the memory write/read is to/from user | 
 | 58 | | or supervisor application space. The examples below use simple "move" | 
 | 59 | | instructions for supervisor mode applications and call _copyin()/_copyout() | 
 | 60 | | for user mode applications. | 
 | 61 | | When installing the 060SP, the _copyin()/_copyout() equivalents for a | 
 | 62 | | given operating system should be substituted. | 
 | 63 | | | 
 | 64 | | The addresses within the 060SP are guaranteed to be on the stack. | 
 | 65 | | The result is that Unix processes are allowed to sleep as a consequence | 
 | 66 | | of a page fault during a _copyout. | 
 | 67 | | | 
 | 68 | | Linux/68k: The _060_[id]mem_{read,write}_{byte,word,long} functions | 
 | 69 | | (i.e. all the known length <= 4) are implemented by single moves | 
 | 70 | | statements instead of (more expensive) copy{in,out} calls, if | 
 | 71 | | working in user space | 
 | 72 |  | 
 | 73 | | | 
 | 74 | | _060_dmem_write(): | 
 | 75 | | | 
 | 76 | | Writes to data memory while in supervisor mode. | 
 | 77 | | | 
 | 78 | | INPUTS: | 
 | 79 | |	a0 - supervisor source address | 
 | 80 | |	a1 - user destination address | 
 | 81 | |	d0 - number of bytes to write | 
 | 82 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 83 | | OUTPUTS: | 
 | 84 | |	d1 - 0 = success, !0 = failure | 
 | 85 | | | 
 | 86 | 	.global		_060_dmem_write | 
 | 87 | _060_dmem_write: | 
 | 88 | 	subq.l		#1,%d0 | 
 | 89 | 	btst		#0x5,0x4(%a6)		| check for supervisor state | 
 | 90 | 	beqs		user_write | 
 | 91 | super_write: | 
 | 92 | 	move.b		(%a0)+,(%a1)+		| copy 1 byte | 
 | 93 | 	dbra		%d0,super_write		| quit if --ctr < 0 | 
 | 94 | 	clr.l		%d1			| return success | 
 | 95 | 	rts | 
 | 96 | user_write: | 
 | 97 | 	move.b		(%a0)+,%d1		| copy 1 byte | 
 | 98 | copyoutae: | 
 | 99 | 	movs.b		%d1,(%a1)+ | 
 | 100 | 	dbra		%d0,user_write		| quit if --ctr < 0 | 
 | 101 | 	clr.l		%d1			| return success | 
 | 102 | 	rts | 
 | 103 |  | 
 | 104 | | | 
 | 105 | | _060_imem_read(), _060_dmem_read(): | 
 | 106 | | | 
 | 107 | | Reads from data/instruction memory while in supervisor mode. | 
 | 108 | | | 
 | 109 | | INPUTS: | 
 | 110 | |	a0 - user source address | 
 | 111 | |	a1 - supervisor destination address | 
 | 112 | |	d0 - number of bytes to read | 
 | 113 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 114 | | OUTPUTS: | 
 | 115 | |	d1 - 0 = success, !0 = failure | 
 | 116 | | | 
 | 117 | 	.global		_060_imem_read | 
 | 118 | 	.global		_060_dmem_read | 
 | 119 | _060_imem_read: | 
 | 120 | _060_dmem_read: | 
 | 121 | 	subq.l		#1,%d0 | 
 | 122 | 	btst		#0x5,0x4(%a6)		| check for supervisor state | 
 | 123 | 	beqs		user_read | 
 | 124 | super_read: | 
 | 125 | 	move.b		(%a0)+,(%a1)+		| copy 1 byte | 
 | 126 | 	dbra		%d0,super_read		| quit if --ctr < 0 | 
 | 127 | 	clr.l		%d1			| return success | 
 | 128 | 	rts | 
 | 129 | user_read: | 
 | 130 | copyinae: | 
 | 131 | 	movs.b		(%a0)+,%d1 | 
 | 132 | 	move.b		%d1,(%a1)+		| copy 1 byte | 
 | 133 | 	dbra		%d0,user_read		| quit if --ctr < 0 | 
 | 134 | 	clr.l		%d1			| return success | 
 | 135 | 	rts | 
 | 136 |  | 
 | 137 | | | 
 | 138 | | _060_dmem_read_byte(): | 
 | 139 | | | 
 | 140 | | Read a data byte from user memory. | 
 | 141 | | | 
 | 142 | | INPUTS: | 
 | 143 | |	a0 - user source address | 
 | 144 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 145 | | OUTPUTS: | 
 | 146 | |	d0 - data byte in d0 | 
 | 147 | |	d1 - 0 = success, !0 = failure | 
 | 148 | | | 
 | 149 | 	.global		_060_dmem_read_byte | 
 | 150 | _060_dmem_read_byte: | 
 | 151 | 	clr.l		%d0			| clear whole longword | 
 | 152 | 	clr.l		%d1			| assume success | 
 | 153 | 	btst		#0x5,0x4(%a6)		| check for supervisor state | 
 | 154 | 	bnes		dmrbs			| supervisor | 
 | 155 | dmrbuae:movs.b		(%a0),%d0		| fetch user byte | 
 | 156 | 	rts | 
 | 157 | dmrbs:	move.b		(%a0),%d0		| fetch super byte | 
 | 158 | 	rts | 
 | 159 |  | 
 | 160 | | | 
 | 161 | | _060_dmem_read_word(): | 
 | 162 | | | 
 | 163 | | Read a data word from user memory. | 
 | 164 | | | 
 | 165 | | INPUTS: | 
 | 166 | |	a0 - user source address | 
 | 167 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 168 | | OUTPUTS: | 
 | 169 | |	d0 - data word in d0 | 
 | 170 | |	d1 - 0 = success, !0 = failure | 
 | 171 | | | 
 | 172 | | _060_imem_read_word(): | 
 | 173 | | | 
 | 174 | | Read an instruction word from user memory. | 
 | 175 | | | 
 | 176 | | INPUTS: | 
 | 177 | |	a0 - user source address | 
 | 178 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 179 | | OUTPUTS: | 
 | 180 | |	d0 - instruction word in d0 | 
 | 181 | |	d1 - 0 = success, !0 = failure | 
 | 182 | | | 
 | 183 | 	.global		_060_dmem_read_word | 
 | 184 | 	.global		_060_imem_read_word | 
 | 185 | _060_dmem_read_word: | 
 | 186 | _060_imem_read_word: | 
 | 187 | 	clr.l		%d1			| assume success | 
 | 188 | 	clr.l		%d0			| clear whole longword | 
 | 189 | 	btst		#0x5,0x4(%a6)		| check for supervisor state | 
 | 190 | 	bnes		dmrws			| supervisor | 
 | 191 | dmrwuae:movs.w		(%a0), %d0		| fetch user word | 
 | 192 | 	rts | 
 | 193 | dmrws:	move.w		(%a0), %d0		| fetch super word | 
 | 194 | 	rts | 
 | 195 |  | 
 | 196 | | | 
 | 197 | | _060_dmem_read_long(): | 
 | 198 | | | 
 | 199 |  | 
 | 200 | | | 
 | 201 | | INPUTS: | 
 | 202 | |	a0 - user source address | 
 | 203 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 204 | | OUTPUTS: | 
 | 205 | |	d0 - data longword in d0 | 
 | 206 | |	d1 - 0 = success, !0 = failure | 
 | 207 | | | 
 | 208 | | _060_imem_read_long(): | 
 | 209 | | | 
 | 210 | | Read an instruction longword from user memory. | 
 | 211 | | | 
 | 212 | | INPUTS: | 
 | 213 | |	a0 - user source address | 
 | 214 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 215 | | OUTPUTS: | 
 | 216 | |	d0 - instruction longword in d0 | 
 | 217 | |	d1 - 0 = success, !0 = failure | 
 | 218 | | | 
 | 219 | 	.global		_060_dmem_read_long | 
 | 220 | 	.global		_060_imem_read_long | 
 | 221 | _060_dmem_read_long: | 
 | 222 | _060_imem_read_long: | 
 | 223 | 	clr.l		%d1			| assume success | 
 | 224 | 	btst		#0x5,0x4(%a6)		| check for supervisor state | 
 | 225 | 	bnes		dmrls			| supervisor | 
 | 226 | dmrluae:movs.l		(%a0),%d0		| fetch user longword | 
 | 227 | 	rts | 
 | 228 | dmrls:	move.l		(%a0),%d0		| fetch super longword | 
 | 229 | 	rts | 
 | 230 |  | 
 | 231 | | | 
 | 232 | | _060_dmem_write_byte(): | 
 | 233 | | | 
 | 234 | | Write a data byte to user memory. | 
 | 235 | | | 
 | 236 | | INPUTS: | 
 | 237 | |	a0 - user destination address | 
 | 238 | |	d0 - data byte in d0 | 
 | 239 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 240 | | OUTPUTS: | 
 | 241 | |	d1 - 0 = success, !0 = failure | 
 | 242 | | | 
 | 243 | 	.global		_060_dmem_write_byte | 
 | 244 | _060_dmem_write_byte: | 
 | 245 | 	clr.l		%d1			| assume success | 
 | 246 | 	btst		#0x5,0x4(%a6)		| check for supervisor state | 
 | 247 | 	bnes		dmwbs			| supervisor | 
 | 248 | dmwbuae:movs.b		%d0,(%a0)		| store user byte | 
 | 249 | 	rts | 
 | 250 | dmwbs:	move.b		%d0,(%a0)		| store super byte | 
 | 251 | 	rts | 
 | 252 |  | 
 | 253 | | | 
 | 254 | | _060_dmem_write_word(): | 
 | 255 | | | 
 | 256 | | Write a data word to user memory. | 
 | 257 | | | 
 | 258 | | INPUTS: | 
 | 259 | |	a0 - user destination address | 
 | 260 | |	d0 - data word in d0 | 
 | 261 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 262 | | OUTPUTS: | 
 | 263 | |	d1 - 0 = success, !0 = failure | 
 | 264 | | | 
 | 265 | 	.global		_060_dmem_write_word | 
 | 266 | _060_dmem_write_word: | 
 | 267 | 	clr.l		%d1			| assume success | 
 | 268 | 	btst		#0x5,0x4(%a6)		| check for supervisor state | 
 | 269 | 	bnes		dmwws			| supervisor | 
 | 270 | dmwwu: | 
 | 271 | dmwwuae:movs.w		%d0,(%a0)		| store user word | 
 | 272 | 	bras		dmwwr | 
 | 273 | dmwws:	move.w		%d0,(%a0)		| store super word | 
 | 274 | dmwwr:	clr.l		%d1			| return success | 
 | 275 | 	rts | 
 | 276 |  | 
 | 277 | | | 
 | 278 | | _060_dmem_write_long(): | 
 | 279 | | | 
 | 280 | | Write a data longword to user memory. | 
 | 281 | | | 
 | 282 | | INPUTS: | 
 | 283 | |	a0 - user destination address | 
 | 284 | |	d0 - data longword in d0 | 
 | 285 | |	0x4(%a6),bit5 - 1 = supervisor mode, 0 = user mode | 
 | 286 | | OUTPUTS: | 
 | 287 | |	d1 - 0 = success, !0 = failure | 
 | 288 | | | 
 | 289 | 	.global		_060_dmem_write_long | 
 | 290 | _060_dmem_write_long: | 
 | 291 | 	clr.l		%d1			| assume success | 
 | 292 | 	btst		#0x5,0x4(%a6)		| check for supervisor state | 
 | 293 | 	bnes		dmwls			| supervisor | 
 | 294 | dmwluae:movs.l		%d0,(%a0)		| store user longword | 
 | 295 | 	rts | 
 | 296 | dmwls:	move.l		%d0,(%a0)		| store super longword | 
 | 297 | 	rts | 
 | 298 |  | 
 | 299 |  | 
 | 300 | #if 0 | 
 | 301 | |############################################### | 
 | 302 |  | 
 | 303 | | | 
 | 304 | | Use these routines if your kernel doesn't have _copyout/_copyin equivalents. | 
 | 305 | | Assumes that D0/D1/A0/A1 are scratch registers. The _copyin/_copyout | 
 | 306 | | below assume that the SFC/DFC have been set previously. | 
 | 307 | | | 
 | 308 | | Linux/68k: These are basically non-inlined versions of | 
 | 309 | | memcpy_{to,from}fs, but without long-transfer optimization | 
 | 310 | | Note: Assumed that SFC/DFC are pointing correctly to user data | 
 | 311 | | space... Should be right, or are there any exceptions? | 
 | 312 |  | 
 | 313 | | | 
 | 314 | | int _copyout(supervisor_addr, user_addr, nbytes) | 
 | 315 | | | 
 | 316 | 	.global		_copyout | 
 | 317 | _copyout: | 
 | 318 | 	move.l		4(%sp),%a0		| source | 
 | 319 | 	move.l		8(%sp),%a1		| destination | 
 | 320 | 	move.l		12(%sp),%d0		| count | 
 | 321 | 	subq.l		#1,%d0 | 
 | 322 | moreout: | 
 | 323 | 	move.b		(%a0)+,%d1		| fetch supervisor byte | 
 | 324 | copyoutae: | 
 | 325 | 	movs.b		%d1,(%a1)+		| store user byte | 
 | 326 | 	dbra		%d0,moreout		| are we through yet? | 
 | 327 | 	moveq		#0,%d0			| return success | 
 | 328 | 	rts | 
 | 329 |  | 
 | 330 | | | 
 | 331 | | int _copyin(user_addr, supervisor_addr, nbytes) | 
 | 332 | | | 
 | 333 | 	.global		_copyin | 
 | 334 | _copyin: | 
 | 335 | 	move.l		4(%sp),%a0		| source | 
 | 336 | 	move.l		8(%sp),%a1		| destination | 
 | 337 | 	move.l		12(%sp),%d0		| count | 
 | 338 |     subq.l      #1,%d0 | 
 | 339 | morein: | 
 | 340 | copyinae: | 
 | 341 | 	movs.b		(%a0)+,%d1		| fetch user byte | 
 | 342 | 	move.b		%d1,(%a1)+		| write supervisor byte | 
 | 343 | 	dbra		%d0,morein		| are we through yet? | 
 | 344 | 	moveq		#0,%d0			| return success | 
 | 345 | 	rts | 
 | 346 | #endif | 
 | 347 |  | 
 | 348 | |########################################################################### | 
 | 349 |  | 
 | 350 | | | 
 | 351 | | _060_real_trace(): | 
 | 352 | | | 
 | 353 | | This is the exit point for the 060FPSP when an instruction is being traced | 
 | 354 | | and there are no other higher priority exceptions pending for this instruction | 
 | 355 | | or they have already been processed. | 
 | 356 | | | 
 | 357 | | The sample code below simply executes an "rte". | 
 | 358 | | | 
 | 359 | 	.global		_060_real_trace | 
 | 360 | _060_real_trace: | 
 | 361 | 	bral	trap | 
 | 362 |  | 
 | 363 | | | 
 | 364 | | _060_real_access(): | 
 | 365 | | | 
 | 366 | | This is the exit point for the 060FPSP when an access error exception | 
 | 367 | | is encountered. The routine below should point to the operating system | 
 | 368 | | handler for access error exceptions. The exception stack frame is an | 
 | 369 | | 8-word access error frame. | 
 | 370 | | | 
 | 371 | | The sample routine below simply executes an "rte" instruction which | 
 | 372 | | is most likely the incorrect thing to do and could put the system | 
 | 373 | | into an infinite loop. | 
 | 374 | | | 
 | 375 | 	.global		_060_real_access | 
 | 376 | _060_real_access: | 
 | 377 | 	bral	buserr | 
 | 378 |  | 
 | 379 |  | 
 | 380 |  | 
 | 381 | | Execption handling for movs access to illegal memory | 
 | 382 | 	.section .fixup,#alloc,#execinstr | 
 | 383 | 	.even | 
 | 384 | 1:	moveq		#-1,%d1 | 
 | 385 | 	rts | 
 | 386 | .section __ex_table,#alloc | 
 | 387 | 	.align 4 | 
 | 388 | 	.long	dmrbuae,1b | 
 | 389 | 	.long	dmrwuae,1b | 
 | 390 | 	.long	dmrluae,1b | 
 | 391 | 	.long	dmwbuae,1b | 
 | 392 | 	.long	dmwwuae,1b | 
 | 393 | 	.long	dmwluae,1b | 
 | 394 | 	.long	copyoutae,1b | 
 | 395 | 	.long	copyinae,1b | 
 | 396 | 	.text |