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