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