esiop.ss revision 1.12
1; $NetBSD: esiop.ss,v 1.12 2002/04/27 18:46:50 bouyer Exp $ 2 3; 4; Copyright (c) 2002 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. Neither the name of the University nor the names of its contributors 18; may be used to endorse or promote products derived from this software 19; without specific prior written permission. 20; 21; THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24; ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31; SUCH DAMAGE. 32; 33 34ARCH 825 35 36; offsets in siop_common_xfer 37ABSOLUTE t_id = 40; 38ABSOLUTE t_msg_in = 48; 39ABSOLUTE t_ext_msg_in = 56; 40ABSOLUTE t_ext_msg_data = 64; 41ABSOLUTE t_msg_out = 72; 42ABSOLUTE t_cmd = 80; 43ABSOLUTE t_status = 88; 44ABSOLUTE t_data = 96; 45 46; offsets in the per-target lun table 47ABSOLUTE target_id = 0x0; 48ABSOLUTE target_luntbl = 0x8; 49ABSOLUTE target_luntbl_tag = 0xc; 50 51;; interrupt codes 52; interrupts that needs a valid target/lun/tag 53ABSOLUTE int_done = 0xff00; 54ABSOLUTE int_msgin = 0xff01; 55ABSOLUTE int_extmsgin = 0xff02; 56ABSOLUTE int_extmsgdata = 0xff03; 57ABSOLUTE int_disc = 0xff04; 58; interrupts that don't have a valid I/T/Q 59ABSOLUTE int_resfail = 0xff80; 60ABSOLUTE int_err = 0xffff; 61 62; We use the various scratch[a-j] registers to keep internal status: 63 64; scratchA1: offset in data DSA (for save data pointer) 65; scratchB: save/restore DSA in data loop 66; scratchC: current target/lun/tag 67; scratchC0: flags 68ABSOLUTE f_c_target = 0x01 ; target valid 69ABSOLUTE f_c_lun = 0x02 ; lun valud 70ABSOLUTE f_c_tag = 0x04 ; tag valid 71ABSOLUTE f_c_data = 0x08 ; data I/O in progress 72ABSOLUTE f_c_data_mask = 0xf7 ; ~f_c_data 73ABSOLUTE f_c_sdp = 0x10 ; got save data pointer message 74; scratchC[1-3]: target/lun/tag 75 76; scratchD: current DSA in start cmd ring 77; scratchE0: index in start cmd ring 78ABSOLUTE ncmd_slots = 256 ; number of slots in CMD ring 79ABSOLUTE ncmd_slots_last = 0 ; == ncmd_slots in a 8bit counter 80; flags in a cmd slot 81ABSOLUTE f_cmd_free = 0x01 ; this slot is free 82ABSOLUTE f_cmd_ignore = 0x02 ; this slot is not free but don't start it 83; offsets in a cmd slot 84ABSOLUTE o_cmd_dsa = 0; also holds f_cmd_* 85; size of a cmd slot (for DSA increments) 86ABSOLUTE cmd_slot_size = 4; 87 88; SCRATCHE1: last status 89 90; SCRATCHE2: current command done slot 91ABSOLUTE ndone_slots = 256 ; number of slots in CMD ring 92ABSOLUTE ndone_slots_last = 0 ; == ndonemd_slots in a 8bit counter 93; SCRATCHF: pointer in command done ring 94 95ENTRY cmdr0; 96ENTRY cmdr1; 97ENTRY cmdr2; 98ENTRY cmdr3; 99ENTRY doner0; 100ENTRY doner1; 101ENTRY doner2; 102ENTRY doner3; 103ENTRY reselect; 104ENTRY led_on1; 105ENTRY led_on2; 106ENTRY led_off; 107ENTRY status; 108ENTRY msgin; 109ENTRY msgin_ack; 110ENTRY get_extmsgdata; 111ENTRY send_msgout; 112ENTRY script_sched; 113ENTRY load_targtable; 114 115EXTERN tlq_offset; 116EXTERN abs_msgin2; 117 118EXTERN abs_sem; a 32bits word used a semaphore between script and driver 119ABSOLUTE sem_done = 0x01; there are pending done commands 120ABSOLUTE sem_start = 0x02; a CMD slot was freed 121 122PROC esiop_script: 123 124no_cmd: 125 LOAD SCRATCHB0, 4, abs_sem; pending done command ? 126 MOVE SCRATCHB0 & sem_done TO SFBR; 127 INTFLY 0, IF NOT 0x00; 128 MOVE SCRATCHB0 | sem_start TO SCRATCHB0; we are there because the 129 STORE NOFLUSH SCRATCHB0, 4, abs_sem; cmd ring is empty 130reselect: 131 MOVE 0x00 TO SCRATCHA1; 132 MOVE 0x00 TO SCRATCHC0; 133 MOVE 0xff TO SCRATCHE1; 134; a NOP by default; patched with MOVE GPREG | 0x01 to GPREG on compile-time 135; option "SIOP_SYMLED" 136led_off: 137 NOP; 138 WAIT RESELECT REL(reselect_fail); 139; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time 140; option "SIOP_SYMLED" 141led_on2: 142 NOP; 143 MOVE SSID & 0x0f to SFBR; 144 MOVE SFBR to SCRATCHC1; 145 MOVE SCRATCHC0 | f_c_target to SCRATCHC0; save target 146 CLEAR CARRY; 147 MOVE SCRATCHC1 SHL SFBR; 148 MOVE SFBR SHL DSA0; target * 4 in dsa 149 MOVE 0x0 to DSA1; 150 MOVE 0x0 to DSA2; 151 MOVE 0x0 to DSA3; 152; load DSA for the target table 153load_targtable: 154 MOVE DSA0 + 0x00 to DSA0; host will patch 0x0 with base of table 155 MOVE DSA1 + 0x00 to DSA1 with carry; 156 MOVE DSA2 + 0x00 to DSA2 with carry; 157 MOVE DSA3 + 0x00 to DSA3 with carry; now dsa -> basetable + target * 4 158 LOAD DSA0, 4, FROM 0; now load DSA for this target 159 SELECT FROM target_id, REL(nextisn); 160nextisn: 161 MOVE 1, abs_msgin2, WHEN MSG_IN; 162 MOVE SFBR & 0x07 to SCRATCHC2; 163 MOVE SCRATCHC0 | f_c_lun to SCRATCHC0; save LUN 164 CLEAR ACK and CARRY; 165 MOVE SCRATCHC2 SHL SFBR; 166 MOVE SFBR SHL SFBR; 167 MOVE SFBR SHL SFBR; lun * 8 168 MOVE DSA0 + SFBR TO DSA0; 169 MOVE DSA1 + 0x0 TO DSA1 with carry; 170 MOVE DSA2 + 0x0 TO DSA2 with carry; 171 MOVE DSA3 + 0x0 TO DSA3 with carry; 172 LOAD SCRATCHB0, 4, from target_luntbl_tag; in case it's a tagged cmd 173 LOAD DSA0, 4, from target_luntbl; load DSA for this LUN 174 JUMP REL(waitphase), WHEN NOT MSG_IN; 175 MOVE 1, abs_msgin2, WHEN MSG_IN; 176 CLEAR ACK; 177 INT int_msgin, IF NOT 0x20; not a simple tag message, let host handle it 178 MOVE 1, abs_msgin2, WHEN MSG_IN; get tag 179 CLEAR ACK; 180 MOVE SFBR to SCRATCHA2; 181 MOVE SFBR to SCRATCHC3; 182 MOVE SCRATCHC0 | f_c_tag to SCRATCHC0; save TAG 183 CALL REL(restoredsa); switch to tag table DSA 184 MOVE 0x0 to SCRATCHA3; 185 CLEAR CARRY; 186 MOVE SCRATCHA2 SHL SCRATCHA2; 187 MOVE SCRATCHA3 SHL SCRATCHA3; 188 MOVE SCRATCHA2 SHL SCRATCHA2; 189 MOVE SCRATCHA3 SHL SCRATCHA3; TAG * 4 to SCRATCHA(2,3) 190 MOVE SCRATCHA2 TO SFBR; 191 MOVE DSA0 + SFBR TO DSA0; 192 MOVE DSA1 + 0x00 TO DSA1 with CARRY; 193 MOVE DSA2 + 0x00 TO DSA2 with CARRY; 194 MOVE DSA3 + 0x00 TO DSA3 with CARRY; 195 MOVE SCRATCHA3 TO SFBR; 196 MOVE DSA1 + SFBR TO DSA1; 197 MOVE DSA2 + 0x00 TO DSA2 with CARRY; 198 MOVE DSA3 + 0x00 TO DSA3 with CARRY; SCRACHA(2,3) + DSA to DSA 199 LOAD DSA0, 4, from 0; load DSA for this tag 200 JUMP REL(waitphase); 201 202reselect_fail: 203 ; check that host asserted SIGP, this'll clear SIGP in ISTAT 204 MOVE CTEST2 & 0x40 TO SFBR; 205 INT int_resfail, IF 0x00; 206script_sched: 207; Load ring DSA 208 MOVE SCRATCHD0 to SFBR; 209 MOVE SFBR to DSA0; 210 MOVE SCRATCHD1 to SFBR; 211 MOVE SFBR to DSA1; 212 MOVE SCRATCHD2 to SFBR; 213 MOVE SFBR to DSA2; 214 MOVE SCRATCHD3 to SFBR; 215 MOVE SFBR to DSA3; 216 LOAD DSA0,4, from o_cmd_dsa; get DSA and flags for this slot 217 MOVE DSA0 & f_cmd_free to SFBR; check flags 218 JUMP REL(no_cmd), IF NOT 0x0; 219 MOVE DSA0 & f_cmd_ignore to SFBR; 220 JUMP REL(ignore_cmd), IF NOT 0x0; 221 LOAD SCRATCHC0, 4, FROM tlq_offset; 222; this slot is busy, attempt to exec command 223 SELECT ATN FROM t_id, REL(reselect); 224; select either succeeded or timed out. 225; if timed out the STO interrupt will be posted at the first SCSI bus access 226; waiting for a valid phase, so we have to do it now. If not a MSG_OUT phase, 227; this is an error anyway (we selected with ATN) 228 INT int_err, WHEN NOT MSG_OUT; 229ignore_cmd: 230 MOVE SCRATCHD0 to SFBR; restore scheduler DSA 231 MOVE SFBR to DSA0; 232 MOVE SCRATCHD1 to SFBR; 233 MOVE SFBR to DSA1; 234 MOVE SCRATCHD2 to SFBR; 235 MOVE SFBR to DSA2; 236 MOVE SCRATCHD3 to SFBR; 237 MOVE SFBR to DSA3; 238 MOVE SCRATCHE0 + 1 to SCRATCHE0; 239 MOVE SCRATCHD0 + cmd_slot_size to SCRATCHD0; 240 MOVE SCRATCHD1 + 0 to SCRATCHD1 WITH CARRY; 241 MOVE SCRATCHD2 + 0 to SCRATCHD2 WITH CARRY; 242 MOVE SCRATCHD3 + 0 to SCRATCHD3 WITH CARRY; 243 MOVE SCRATCHE0 TO SFBR; 244 JUMP REL(handle_cmd), IF NOT ncmd_slots_last; 245; reset pointers to beggining of area 246cmdr0: 247 MOVE 0xff to SCRATCHD0; correct value will be patched by driver 248cmdr1: 249 MOVE 0xff to SCRATCHD1; 250cmdr2: 251 MOVE 0xff to SCRATCHD2; 252cmdr3: 253 MOVE 0xff to SCRATCHD3; 254 MOVE 0x00 to SCRATCHE0; 255handle_cmd: 256; to avoid race condition we have to load the DSA value before setting the 257; free flag, so we have to use a temp register. 258; use SCRATCHB0 so that we can CALL restoredsa later 259 LOAD SCRATCHB0, 4, FROM o_cmd_dsa; load DSA for this command in temp reg 260 MOVE SCRATCHB0 | f_cmd_free to SCRATCHB0; mark slot as free 261 STORE noflush SCRATCHB0, 4, FROM o_cmd_dsa; 262 MOVE SCRATCHB0 & f_cmd_ignore to SFBR; 263 JUMP REL(script_sched), IF NOT 0x00; next command if ignore 264 MOVE SCRATCHB0 & 0xfc to SCRATCHB0; clear f_cmd_* 265 CALL REL(restoredsa); and move SCRATCHB to DSA 266 LOAD SCRATCHB0, 4, abs_sem; 267 MOVE SCRATCHB0 | sem_start TO SCRATCHB0; 268 STORE NOFLUSH SCRATCHB0, 4, abs_sem; 269 270; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time 271; option "SIOP_SYMLED" 272led_on1: 273 NOP; 274 MOVE 0x00 TO SCRATCHA1; 275 MOVE 0xff TO SCRATCHE1; 276;we can now send our identify message 277send_msgout: ; entry point for msgout after a msgin or status phase 278 SET ATN; 279 CLEAR ACK; 280msgout: 281 MOVE FROM t_msg_out, WHEN MSG_OUT; 282 CLEAR ATN; 283 JUMP REL(waitphase); 284 285msgin_ack: 286 CLEAR ACK; 287waitphase: 288 JUMP REL(msgout), WHEN MSG_OUT; 289 JUMP REL(msgin), WHEN MSG_IN; 290 JUMP REL(dataout), WHEN DATA_OUT; 291 JUMP REL(datain), WHEN DATA_IN; 292 JUMP REL(cmdout), WHEN CMD; 293 JUMP REL(status), WHEN STATUS; 294 INT int_err; 295 296 297handle_sdp: 298 CLEAR ACK; 299 MOVE SCRATCHC0 | f_c_sdp TO SCRATCHC0; 300 ; should get a disconnect message now 301msgin: 302 CLEAR ATN 303 MOVE FROM t_msg_in, WHEN MSG_IN; 304handle_msgin: 305 JUMP REL(handle_cmpl), IF 0x00 ; command complete message 306 JUMP REL(handle_sdp), IF 0x02 ; save data pointer message 307 JUMP REL(handle_extin), IF 0x01 ; extended message 308 INT int_msgin, IF NOT 0x04; 309 CALL REL(disconnect) ; disconnect message 310; if we didn't get sdp, or if offset is 0, no need to interrupt 311 MOVE SCRATCHC0 & f_c_sdp TO SFBR; 312 JUMP REL(script_sched), if 0x00; 313 MOVE SCRATCHA1 TO SFBR; 314 JUMP REL(script_sched), if 0x00; 315; Ok, we need to save data pointers 316 INT int_disc; 317 318cmdout: 319 MOVE FROM t_cmd, WHEN CMD; 320 JUMP REL(waitphase); 321status: 322 MOVE FROM t_status, WHEN STATUS; 323 MOVE SFBR TO SCRATCHE1; 324 JUMP REL(waitphase); 325datain: 326 CALL REL(savedsa); 327 MOVE SCRATCHC0 | f_c_data TO SCRATCHC0; 328 datain_loop: 329 MOVE FROM t_data, WHEN DATA_IN; 330 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset 331 MOVE DSA0 + 8 to DSA0; 332 MOVE DSA1 + 0 to DSA1 WITH CARRY; 333 MOVE DSA2 + 0 to DSA2 WITH CARRY; 334 MOVE DSA3 + 0 to DSA3 WITH CARRY; 335 JUMP REL(datain_loop), WHEN DATA_IN; 336 CALL REL(restoredsa); 337 MOVE SCRATCHC0 & f_c_data_mask TO SCRATCHC0; 338 JUMP REL(waitphase); 339 340dataout: 341 CALL REL(savedsa); 342 MOVE SCRATCHC0 | f_c_data TO SCRATCHC0; 343dataout_loop: 344 MOVE FROM t_data, WHEN DATA_OUT; 345 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset 346 MOVE DSA0 + 8 to DSA0; 347 MOVE DSA1 + 0 to DSA1 WITH CARRY; 348 MOVE DSA2 + 0 to DSA2 WITH CARRY; 349 MOVE DSA3 + 0 to DSA3 WITH CARRY; 350 JUMP REL(dataout_loop), WHEN DATA_OUT; 351 CALL REL(restoredsa); 352 MOVE SCRATCHC0 & f_c_data_mask TO SCRATCHC0; 353 JUMP REL(waitphase); 354 355savedsa: 356 MOVE DSA0 to SFBR; 357 MOVE SFBR to SCRATCHB0; 358 MOVE DSA1 to SFBR; 359 MOVE SFBR to SCRATCHB1; 360 MOVE DSA2 to SFBR; 361 MOVE SFBR to SCRATCHB2; 362 MOVE DSA3 to SFBR; 363 MOVE SFBR to SCRATCHB3; 364 RETURN; 365 366restoredsa: 367 MOVE SCRATCHB0 TO SFBR; 368 MOVE SFBR TO DSA0; 369 MOVE SCRATCHB1 TO SFBR; 370 MOVE SFBR TO DSA1; 371 MOVE SCRATCHB2 TO SFBR; 372 MOVE SFBR TO DSA2; 373 MOVE SCRATCHB3 TO SFBR; 374 MOVE SFBR TO DSA3; 375 RETURN; 376 377disconnect: 378 MOVE SCNTL2 & 0x7f TO SCNTL2; 379 CLEAR ATN; 380 CLEAR ACK; 381 WAIT DISCONNECT; 382 RETURN; 383 384handle_cmpl: 385 CALL REL(disconnect); 386 MOVE SCRATCHE1 to SFBR; 387 INT int_done, IF NOT 0x00; if status is not "done", let host handle it 388 MOVE SCRATCHF0 to SFBR; load pointer in done ring 389 MOVE SFBR to DSA0; 390 MOVE SCRATCHF1 to SFBR; 391 MOVE SFBR to DSA1; 392 MOVE SCRATCHF2 to SFBR; 393 MOVE SFBR to DSA2; 394 MOVE SCRATCHF3 to SFBR; 395 MOVE SFBR to DSA3; 396wait_free: 397 LOAD SCRATCHA0, 1, from 0; 398 MOVE SCRATCHA0 to SFBR; 399 JUMP REL(wait_free), if not 0; wait for slot to be free 400 STORE NOFLUSH SCRATCHC0, 4, from 0; save current target/lun/flag 401 MOVE SCRATCHF0 + 4 to SCRATCHF0; advance to next slot 402 MOVE SCRATCHF1 + 0 to SCRATCHF1 with carry; 403 MOVE SCRATCHF2 + 0 to SCRATCHF2 with carry; 404 MOVE SCRATCHF3 + 0 to SCRATCHF3 with carry; 405 MOVE SCRATCHE2 + 1 to SCRATCHE2; 406 MOVE SCRATCHE2 to SFBR; 407 JUMP REL(is_done), if not ndone_slots_last; 408doner0: 409 MOVE 0xff to SCRATCHF0; driver will change 0xff to base of ring 410doner1: 411 MOVE 0xff to SCRATCHF1; 412doner2: 413 MOVE 0xff to SCRATCHF2; 414doner3: 415 MOVE 0xff to SCRATCHF3; 416 MOVE 0 to SCRATCHE2; 417is_done: 418 LOAD SCRATCHB0, 4, abs_sem; signal that a command is done 419 MOVE SCRATCHB0 | sem_done TO SCRATCHB0; 420 STORE NOFLUSH SCRATCHB0, 4, abs_sem; 421 JUMP REL(script_sched); and attempt next command 422 423handle_extin: 424 CLEAR ACK; 425 MOVE FROM t_ext_msg_in, WHEN MSG_IN; 426 INT int_extmsgin; /* let host fill in t_ext_msg_data */ 427get_extmsgdata: 428 CLEAR ACK; 429 MOVE FROM t_ext_msg_data, WHEN MSG_IN; 430 INT int_extmsgdata; 431 432PROC esiop_led_on: 433 MOVE GPREG & 0xfe TO GPREG; 434 435PROC esiop_led_off: 436 MOVE GPREG | 0x01 TO GPREG; 437