1 ; $NetBSD: siop.ss,v 1.21 2009/10/19 18:41:13 bouyer Exp $ 2 3 ; 4 ; Copyright (c) 2000 Manuel Bouyer. 5 ; 6 ; Redistribution and use in source and binary forms, with or without 7 ; modification, are permitted provided that the following conditions 8 ; are met: 9 ; 1. Redistributions of source code must retain the above copyright 10 ; notice, this list of conditions and the following disclaimer. 11 ; 2. Redistributions in binary form must reproduce the above copyright 12 ; notice, this list of conditions and the following disclaimer in the 13 ; documentation and/or other materials provided with the distribution. 14 ; 15 ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 ; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 ; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26 ARCH 720 27 28 ; offsets in siop_common_xfer 29 ABSOLUTE t_id = 40; 30 ABSOLUTE t_msg_in = 48; 31 ABSOLUTE t_ext_msg_in = 56; 32 ABSOLUTE t_ext_msg_data = 64; 33 ABSOLUTE t_msg_out = 72; 34 ABSOLUTE t_cmd = 80; 35 ABSOLUTE t_status = 88; 36 ABSOLUTE t_data = 96; 37 38 ;; interrupt codes 39 ; interrupts that need a valid DSA 40 ABSOLUTE int_done = 0xff00; 41 ABSOLUTE int_msgin = 0xff01; 42 ABSOLUTE int_extmsgin = 0xff02; 43 ABSOLUTE int_extmsgdata = 0xff03; 44 ABSOLUTE int_disc = 0xff04; 45 ABSOLUTE int_saveoffset = 0xff05; 46 ; interrupts that don't have a valid DSA 47 ABSOLUTE int_reseltarg = 0xff80; 48 ABSOLUTE int_resellun = 0xff81; 49 ABSOLUTE int_reseltag = 0xff82; 50 ABSOLUTE int_resfail = 0xff83; 51 ABSOLUTE int_err = 0xffff; 52 53 ; flags for scratcha0 54 ABSOLUTE flag_sdp = 0x01 ; got save data pointer 55 ABSOLUTE flag_data = 0x02 ; we're in data phase 56 ABSOLUTE flag_data_mask = 0xfd ; ~flag_data 57 58 ; main script symbols 59 60 ENTRY waitphase; 61 ENTRY send_msgout; 62 ENTRY msgout; 63 ENTRY msgin; 64 ENTRY handle_msgin; 65 ENTRY msgin_ack; 66 ENTRY dataout; 67 ENTRY datain; 68 ENTRY cmdout; 69 ENTRY status; 70 ENTRY disconnect; 71 ENTRY reselect; 72 ENTRY reselected; 73 ENTRY selected; 74 ENTRY script_sched; 75 ENTRY script_sched_slot0; 76 ENTRY get_extmsgdata; 77 ENTRY resel_targ0; 78 ENTRY msgin_space; 79 ENTRY lunsw_return; 80 ENTRY led_on1; 81 ENTRY led_on2; 82 ENTRY led_off; 83 EXTERN abs_script_sched_slot0; 84 EXTERN abs_targ0; 85 EXTERN abs_msgin; 86 87 ; lun switch symbols 88 ENTRY lun_switch_entry; 89 ENTRY resel_lun0; 90 ENTRY restore_scntl3; 91 EXTERN abs_lunsw_return; 92 93 ; tag switch symbols 94 ENTRY tag_switch_entry; 95 ENTRY resel_tag0; 96 EXTERN abs_tag0; 97 98 ; command reselect script symbols 99 ENTRY rdsa0; 100 ENTRY rdsa1; 101 ENTRY rdsa2; 102 ENTRY rdsa3; 103 ENTRY ldsa_reload_dsa; 104 ENTRY ldsa_select; 105 ENTRY ldsa_data; 106 107 EXTERN ldsa_abs_reselected; 108 EXTERN ldsa_abs_reselect; 109 EXTERN ldsa_abs_selected; 110 EXTERN ldsa_abs_data; 111 EXTERN ldsa_abs_slot; 112 113 ; main script 114 115 PROC siop_script: 116 117 reselected: 118 ; starting a new session, init 'local variables' 119 MOVE 0 to SCRATCHA0 ; flags 120 MOVE 0 to SCRATCHA1 ; DSA offset (for S/G save data pointer) 121 MOVE SCRATCHA3 to SFBR ; pending message ? 122 JUMP REL(handle_msgin), IF not 0x20; 123 waitphase: 124 JUMP REL(msgout), WHEN MSG_OUT; 125 JUMP REL(msgin), WHEN MSG_IN; 126 JUMP REL(dataout), WHEN DATA_OUT; 127 JUMP REL(datain), WHEN DATA_IN; 128 JUMP REL(cmdout), WHEN CMD; 129 JUMP REL(status), WHEN STATUS; 130 INT int_err; 131 132 reselect_fail: 133 ; check that host asserted SIGP, this'll clear SIGP in ISTAT 134 MOVE CTEST2 & 0x40 TO SFBR; 135 INT int_resfail, IF 0x00; 136 ; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time 137 ; option "SIOP_SYMLED" 138 led_on1: 139 NOP; 140 script_sched: 141 ; Clear DSA and init status 142 MOVE 0xff to DSA0; 143 MOVE 0xff to DSA1; 144 MOVE 0xff to DSA2; 145 MOVE 0xff to DSA3; 146 MOVE 0 to SCRATCHA0 ; flags 147 MOVE 0 to SCRATCHA1 ; DSA offset (for S/G save data pointer) 148 ; the script scheduler: siop_start() we set the absolute jump addr, and then 149 ; changes the FALSE to TRUE. The select script will change it back to false 150 ; once the target is selected. 151 ; The RAM could hold 370 slot entry, we limit it to 40. Should be more than 152 ; enough. 153 script_sched_slot0: 154 JUMP abs_script_sched_slot0, IF FALSE; 155 JUMP abs_script_sched_slot0, IF FALSE; 156 JUMP abs_script_sched_slot0, IF FALSE; 157 JUMP abs_script_sched_slot0, IF FALSE; 158 JUMP abs_script_sched_slot0, IF FALSE; 159 JUMP abs_script_sched_slot0, IF FALSE; 160 JUMP abs_script_sched_slot0, IF FALSE; 161 JUMP abs_script_sched_slot0, IF FALSE; 162 JUMP abs_script_sched_slot0, IF FALSE; 163 JUMP abs_script_sched_slot0, IF FALSE; 164 JUMP abs_script_sched_slot0, IF FALSE; 165 JUMP abs_script_sched_slot0, IF FALSE; 166 JUMP abs_script_sched_slot0, IF FALSE; 167 JUMP abs_script_sched_slot0, IF FALSE; 168 JUMP abs_script_sched_slot0, IF FALSE; 169 JUMP abs_script_sched_slot0, IF FALSE; 170 JUMP abs_script_sched_slot0, IF FALSE; 171 JUMP abs_script_sched_slot0, IF FALSE; 172 JUMP abs_script_sched_slot0, IF FALSE; 173 JUMP abs_script_sched_slot0, IF FALSE; 174 JUMP abs_script_sched_slot0, IF FALSE; 175 JUMP abs_script_sched_slot0, IF FALSE; 176 JUMP abs_script_sched_slot0, IF FALSE; 177 JUMP abs_script_sched_slot0, IF FALSE; 178 JUMP abs_script_sched_slot0, IF FALSE; 179 JUMP abs_script_sched_slot0, IF FALSE; 180 JUMP abs_script_sched_slot0, IF FALSE; 181 JUMP abs_script_sched_slot0, IF FALSE; 182 JUMP abs_script_sched_slot0, IF FALSE; 183 JUMP abs_script_sched_slot0, IF FALSE; 184 JUMP abs_script_sched_slot0, IF FALSE; 185 JUMP abs_script_sched_slot0, IF FALSE; 186 JUMP abs_script_sched_slot0, IF FALSE; 187 JUMP abs_script_sched_slot0, IF FALSE; 188 JUMP abs_script_sched_slot0, IF FALSE; 189 JUMP abs_script_sched_slot0, IF FALSE; 190 JUMP abs_script_sched_slot0, IF FALSE; 191 JUMP abs_script_sched_slot0, IF FALSE; 192 JUMP abs_script_sched_slot0, IF FALSE; 193 JUMP abs_script_sched_slot0, IF FALSE; 194 ; Nothing to do, wait for reselect 195 reselect: 196 ; Clear DSA and init status 197 MOVE 0xff to DSA0; 198 MOVE 0xff to DSA1; 199 MOVE 0xff to DSA2; 200 MOVE 0xff to DSA3; 201 MOVE 0x00 to SCRATCHA2; no tag 202 MOVE 0x20 to SCRATCHA3; simple tag msg, ignored by reselected: 203 ; a NOP by default; patched with MOVE GPREG | 0x01 to GPREG on compile-time 204 ; option "SIOP_SYMLED" 205 led_off: 206 NOP; 207 WAIT RESELECT REL(reselect_fail) 208 ; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time 209 ; option "SIOP_SYMLED" 210 led_on2: 211 NOP; 212 MOVE SSID & 0x8f to SFBR 213 MOVE SFBR to SCRATCHA0 ; save reselect ID 214 ; find the right param for this target 215 resel_targ0: 216 JUMP abs_targ0, IF 0xff; 217 JUMP abs_targ0, IF 0xff; 218 JUMP abs_targ0, IF 0xff; 219 JUMP abs_targ0, IF 0xff; 220 JUMP abs_targ0, IF 0xff; 221 JUMP abs_targ0, IF 0xff; 222 JUMP abs_targ0, IF 0xff; 223 JUMP abs_targ0, IF 0xff; 224 JUMP abs_targ0, IF 0xff; 225 JUMP abs_targ0, IF 0xff; 226 JUMP abs_targ0, IF 0xff; 227 JUMP abs_targ0, IF 0xff; 228 JUMP abs_targ0, IF 0xff; 229 JUMP abs_targ0, IF 0xff; 230 JUMP abs_targ0, IF 0xff; 231 INT int_reseltarg; 232 lunsw_return: 233 MOVE 1, abs_msgin, WHEN MSG_IN; 234 MOVE SFBR & 0x07 to SCRATCHA1; save LUN 235 CLEAR ACK; 236 RETURN, WHEN NOT MSG_IN; If no more message, jump to lun sw 237 MOVE 1, abs_msgin, WHEN MSG_IN; 238 CLEAR ACK; 239 MOVE SFBR to SCRATCHA3; save message 240 RETURN, IF NOT 0x20; jump to lun sw if not simple tag msg 241 MOVE 1, abs_msgin, WHEN MSG_IN; get tag 242 CLEAR ACK; 243 MOVE SFBR to SCRATCHA2; save tag 244 RETURN; jump to lun sw 245 246 handle_sdp: 247 CLEAR ACK; 248 MOVE SCRATCHA0 | flag_sdp TO SCRATCHA0; 249 ; should get a disconnect message now 250 msgin: 251 CLEAR ATN 252 MOVE FROM t_msg_in, WHEN MSG_IN; 253 handle_msgin: 254 JUMP REL(handle_cmpl), IF 0x00 ; command complete message 255 JUMP REL(handle_sdp), IF 0x02 ; save data pointer message 256 JUMP REL(handle_extin), IF 0x01 ; extended message 257 INT int_msgin, IF not 0x04; 258 CALL REL(disconnect) ; disconnect message; 259 ; if we didn't get sdp, no need to interrupt 260 MOVE SCRATCHA0 & flag_sdp TO SFBR; 261 INT int_disc, IF not 0x00; 262 ; update offset if we did some data transfer 263 MOVE SCRATCHA1 TO SFBR; 264 JUMP REL(script_sched), if 0x00; 265 INT int_saveoffset; 266 267 msgin_ack: 268 selected: 269 CLEAR ACK; 270 JUMP REL(waitphase); 271 272 ; entry point for msgout after a msgin or status phase 273 send_msgout: 274 SET ATN; 275 CLEAR ACK; 276 msgout: 277 MOVE FROM t_msg_out, WHEN MSG_OUT; 278 CLEAR ATN; 279 JUMP REL(waitphase); 280 cmdout: 281 MOVE FROM t_cmd, WHEN CMD; 282 JUMP REL(waitphase); 283 status: 284 MOVE FROM t_status, WHEN STATUS; 285 JUMP REL(waitphase); 286 datain: 287 CALL REL(savedsa); 288 MOVE SCRATCHA0 | flag_data TO SCRATCHA0; 289 datain_loop: 290 MOVE FROM t_data, WHEN DATA_IN; 291 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset 292 MOVE DSA0 + 8 to DSA0; 293 MOVE DSA1 + 0 to DSA1 WITH CARRY; 294 MOVE DSA2 + 0 to DSA2 WITH CARRY; 295 MOVE DSA3 + 0 to DSA3 WITH CARRY; 296 JUMP REL(datain_loop), WHEN DATA_IN; 297 CALL REL(restoredsa); 298 MOVE SCRATCHA0 & flag_data_mask TO SCRATCHA0; 299 JUMP REL(waitphase); 300 301 dataout: 302 CALL REL(savedsa); 303 MOVE SCRATCHA0 | flag_data TO SCRATCHA0; 304 dataout_loop: 305 MOVE FROM t_data, WHEN DATA_OUT; 306 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset 307 MOVE DSA0 + 8 to DSA0; 308 MOVE DSA1 + 0 to DSA1 WITH CARRY; 309 MOVE DSA2 + 0 to DSA2 WITH CARRY; 310 MOVE DSA3 + 0 to DSA3 WITH CARRY; 311 JUMP REL(dataout_loop), WHEN DATA_OUT; 312 CALL REL(restoredsa); 313 MOVE SCRATCHA0 & flag_data_mask TO SCRATCHA0; 314 JUMP REL(waitphase); 315 316 savedsa: 317 MOVE DSA0 to SFBR; 318 MOVE SFBR to SCRATCHB0; 319 MOVE DSA1 to SFBR; 320 MOVE SFBR to SCRATCHB1; 321 MOVE DSA2 to SFBR; 322 MOVE SFBR to SCRATCHB2; 323 MOVE DSA3 to SFBR; 324 MOVE SFBR to SCRATCHB3; 325 RETURN; 326 327 restoredsa: 328 MOVE SCRATCHB0 TO SFBR; 329 MOVE SFBR TO DSA0; 330 MOVE SCRATCHB1 TO SFBR; 331 MOVE SFBR TO DSA1; 332 MOVE SCRATCHB2 TO SFBR; 333 MOVE SFBR TO DSA2; 334 MOVE SCRATCHB3 TO SFBR; 335 MOVE SFBR TO DSA3; 336 RETURN; 337 338 disconnect: 339 MOVE SCNTL2 & 0x7f TO SCNTL2; 340 CLEAR ATN; 341 CLEAR ACK; 342 WAIT DISCONNECT; 343 RETURN; 344 345 handle_cmpl: 346 CALL REL(disconnect); 347 INT int_done; 348 349 handle_extin: 350 CLEAR ACK; 351 MOVE FROM t_ext_msg_in, WHEN MSG_IN; 352 INT int_extmsgin; /* let host fill in t_ext_msg_data */ 353 get_extmsgdata: 354 CLEAR ACK; 355 MOVE FROM t_ext_msg_data, WHEN MSG_IN; 356 INT int_extmsgdata; 357 msgin_space: 358 NOP; space to store msgin when reselect 359 360 361 ;; per-target switch script for LUNs 362 ; hack: we first do a call to the target-specific code, so that a return 363 ; in the main switch will jump to the lun switch. 364 PROC lun_switch: 365 restore_scntl3: 366 MOVE 0xff TO SCNTL3; 367 MOVE 0xff TO SXFER; 368 JUMP abs_lunsw_return; 369 lun_switch_entry: 370 CALL REL(restore_scntl3); 371 MOVE SCRATCHA1 TO SFBR; 372 resel_lun0: 373 INT int_resellun; 374 375 ;; Per-device switch script for tag 376 PROC tag_switch: 377 tag_switch_entry: 378 MOVE SCRATCHA2 TO SFBR; restore tag 379 resel_tag0: 380 JUMP abs_tag0, IF 0x00; 381 JUMP abs_tag0, IF 0x01; 382 JUMP abs_tag0, IF 0x02; 383 JUMP abs_tag0, IF 0x03; 384 JUMP abs_tag0, IF 0x04; 385 JUMP abs_tag0, IF 0x05; 386 JUMP abs_tag0, IF 0x06; 387 JUMP abs_tag0, IF 0x07; 388 JUMP abs_tag0, IF 0x08; 389 JUMP abs_tag0, IF 0x09; 390 JUMP abs_tag0, IF 0x0a; 391 JUMP abs_tag0, IF 0x0b; 392 JUMP abs_tag0, IF 0x0c; 393 JUMP abs_tag0, IF 0x0d; 394 JUMP abs_tag0, IF 0x0e; 395 JUMP abs_tag0, IF 0x0f; 396 INT int_reseltag; 397 398 ;; per-command script: select, and called after a reselect to load DSA 399 400 PROC load_dsa: 401 ; Can't use MOVE MEMORY to load DSA, doesn't work I/O mapped 402 rdsa0: 403 MOVE 0xf0 to DSA0; 404 rdsa1: 405 MOVE 0xf1 to DSA1; 406 rdsa2: 407 MOVE 0xf2 to DSA2; 408 rdsa3: 409 MOVE 0xf3 to DSA3; 410 RETURN; 411 ldsa_reload_dsa: 412 CALL REL(rdsa0); 413 JUMP ldsa_abs_reselected; 414 ldsa_select: 415 CALL REL(rdsa0); 416 SELECT ATN FROM t_id, ldsa_abs_reselect; 417 MOVE MEMORY 4, ldsa_abs_data, ldsa_abs_slot; 418 JUMP ldsa_abs_selected; 419 ldsa_data: 420 NOP; contains data used by the MOVE MEMORY 421 422 PROC siop_led_on: 423 MOVE GPREG & 0xfe TO GPREG; 424 425 PROC siop_led_off: 426 MOVE GPREG | 0x01 TO GPREG; 427