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