1 1.27 andvar /* $NetBSD: scsi_1185.c,v 1.27 2024/07/05 20:19:43 andvar Exp $ */ 2 1.3 tsubai 3 1.1 tsubai /* 4 1.1 tsubai * Copyright (c) 1992, 1993 5 1.1 tsubai * The Regents of the University of California. All rights reserved. 6 1.1 tsubai * 7 1.1 tsubai * This code is derived from software contributed to Berkeley by 8 1.1 tsubai * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. 9 1.1 tsubai * 10 1.1 tsubai * Redistribution and use in source and binary forms, with or without 11 1.1 tsubai * modification, are permitted provided that the following conditions 12 1.1 tsubai * are met: 13 1.1 tsubai * 1. Redistributions of source code must retain the above copyright 14 1.1 tsubai * notice, this list of conditions and the following disclaimer. 15 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 tsubai * notice, this list of conditions and the following disclaimer in the 17 1.1 tsubai * documentation and/or other materials provided with the distribution. 18 1.13 agc * 3. Neither the name of the University nor the names of its contributors 19 1.1 tsubai * may be used to endorse or promote products derived from this software 20 1.1 tsubai * without specific prior written permission. 21 1.1 tsubai * 22 1.1 tsubai * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 tsubai * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 tsubai * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 tsubai * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 tsubai * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 tsubai * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 tsubai * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 tsubai * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 tsubai * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 tsubai * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 tsubai * SUCH DAMAGE. 33 1.1 tsubai * 34 1.1 tsubai * from: $Hdr: scsi_1185.c,v 4.300 91/06/09 06:22:20 root Rel41 $ SONY 35 1.1 tsubai * 36 1.1 tsubai * @(#)scsi_1185.c 8.1 (Berkeley) 6/11/93 37 1.1 tsubai */ 38 1.1 tsubai 39 1.1 tsubai /* 40 1.1 tsubai * Copyright (c) 1989- by SONY Corporation. 41 1.4 tsubai * 42 1.1 tsubai * scsi_1185.c 43 1.1 tsubai * 44 1.1 tsubai * CXD1185Q 45 1.1 tsubai * SCSI bus low level common routines 46 1.14 wiz * for one CPU machine 47 1.4 tsubai * 48 1.1 tsubai * MODIFY HISTORY: 49 1.1 tsubai * 50 1.1 tsubai * DMAC_WAIT --- DMAC_0266 wo tukau-baai, DMAC mata-wa SCSI-chip ni 51 1.1 tsubai * tuzukete access suru-baai, 52 1.1 tsubai * kanarazu wait wo ireru-beshi ! 53 1.1 tsubai */ 54 1.12 lukem 55 1.12 lukem #include <sys/cdefs.h> 56 1.27 andvar __KERNEL_RCSID(0, "$NetBSD: scsi_1185.c,v 1.27 2024/07/05 20:19:43 andvar Exp $"); 57 1.1 tsubai 58 1.20 matt #define __INTR_PRIVATE 59 1.1 tsubai #include <sys/param.h> 60 1.1 tsubai #include <sys/systm.h> 61 1.4 tsubai #include <sys/device.h> 62 1.20 matt #include <sys/intr.h> 63 1.4 tsubai 64 1.10 thorpej #include <uvm/uvm_extern.h> 65 1.10 thorpej 66 1.4 tsubai #include <dev/scsipi/scsi_all.h> 67 1.4 tsubai #include <dev/scsipi/scsipi_all.h> 68 1.4 tsubai #include <dev/scsipi/scsiconf.h> 69 1.1 tsubai 70 1.23 christos #include <mips/locore.h> 71 1.23 christos #include <mips/cache.h> 72 1.23 christos 73 1.1 tsubai #include <machine/cpu.h> 74 1.4 tsubai #include <machine/intr.h> 75 1.4 tsubai #include <machine/machConst.h> 76 1.1 tsubai 77 1.8 thorpej 78 1.2 thorpej #include <newsmips/dev/screg_1185.h> 79 1.4 tsubai #include <newsmips/dev/scsireg.h> 80 1.1 tsubai 81 1.19 tsutsui #include "ioconf.h" 82 1.19 tsutsui 83 1.4 tsubai #if defined(news3400) 84 1.2 thorpej # include <newsmips/dev/dmac_0448.h> 85 1.1 tsubai # ifndef NDMACMAP 86 1.4 tsubai # define NDMACMAP 144 87 1.1 tsubai # endif 88 1.1 tsubai #endif 89 1.1 tsubai 90 1.1 tsubai #define ABORT_SYNCTR_MES_FROM_TARGET 91 1.1 tsubai #define SCSI_1185AQ 92 1.1 tsubai #define RESET_RECOVER 93 1.1 tsubai #define DMAC_MAP_INIT /* for nws-3700 parity error */ 94 1.1 tsubai #define APAD_ALWAYS_ON 95 1.1 tsubai 96 1.4 tsubai #define CHECK_LOOP_CNT 60 97 1.4 tsubai #define RSL_LOOP_CNT 60 98 1.1 tsubai 99 1.1 tsubai #ifndef DMAC_MAP_INIT 100 1.1 tsubai # define MAP_OVER_ACCESS /* for nws-3700 parity error */ 101 1.1 tsubai #endif 102 1.1 tsubai 103 1.1 tsubai #undef CHECK_MRQ 104 1.1 tsubai 105 1.1 tsubai #ifdef NOT_SUPPORT_SYNCTR 106 1.4 tsubai # define MAX_OFFSET_BYTES 0 107 1.1 tsubai #else 108 1.4 tsubai # define MAX_OFFSET_BYTES MAX_OFFSET 109 1.1 tsubai #endif 110 1.1 tsubai 111 1.1 tsubai #define act_point spoint 112 1.1 tsubai #define act_trcnt stcnt 113 1.1 tsubai #define act_tag stag 114 1.1 tsubai #define act_offset soffset 115 1.1 tsubai 116 1.4 tsubai #define splscsi splsc 117 1.1 tsubai 118 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 119 1.25 tsutsui #define DMAC_WAIT0 __nothing 120 1.1 tsubai #else 121 1.25 tsutsui #define DMAC_WAIT0 DMAC_WAIT /* see MODIFY HISTORY comment above */ 122 1.1 tsubai #endif 123 1.1 tsubai 124 1.1 tsubai #ifdef DMAC_MAP_INIT 125 1.4 tsubai static int dmac_map_init = 0; 126 1.1 tsubai #endif 127 1.1 tsubai 128 1.1 tsubai /* 129 1.1 tsubai * command flag status 130 1.1 tsubai */ 131 1.1 tsubai #define CF_SET 1 132 1.1 tsubai #define CF_SEND 2 133 1.1 tsubai #define CF_ENOUGH 3 134 1.1 tsubai #define CF_EXEC 4 135 1.1 tsubai 136 1.4 tsubai #define SEL_TIMEOUT_VALUE 0x7a 137 1.1 tsubai 138 1.15 tsutsui void sc_send(struct sc_scb *, int, int); 139 1.15 tsutsui int scintr(void); 140 1.15 tsutsui void scsi_hardreset(void); 141 1.15 tsutsui void scsi_chipreset(struct sc_softc *); 142 1.15 tsutsui void scsi_softreset(struct sc_softc *); 143 1.15 tsutsui int sc_busy(struct sc_softc *, int); 144 1.15 tsutsui 145 1.15 tsutsui static int WAIT_STATR_BITCLR(int); 146 1.15 tsutsui static int WAIT_STATR_BITSET(int); 147 1.15 tsutsui static void SET_CMD(struct sc_softc *, int); 148 1.15 tsutsui static void SET_CNT(int); 149 1.15 tsutsui static int GET_CNT(void); 150 1.19 tsutsui static void GET_INTR(uint8_t *, uint8_t *); 151 1.15 tsutsui static void sc_start(struct sc_softc *); 152 1.15 tsutsui static void sc_resel(struct sc_softc *); 153 1.15 tsutsui static void sc_discon(struct sc_softc *); 154 1.15 tsutsui static void sc_pmatch(struct sc_softc *); 155 1.15 tsutsui static void flush_fifo(struct sc_softc *); 156 1.15 tsutsui static void sc_cout(struct sc_softc *, struct sc_chan_stat *); 157 1.15 tsutsui static void sc_min(struct sc_softc *, struct sc_chan_stat *); 158 1.15 tsutsui static void sc_mout(struct sc_softc *, struct sc_chan_stat *); 159 1.15 tsutsui static void sc_sin(struct sc_softc *, volatile struct sc_chan_stat *); 160 1.15 tsutsui static void sc_dio(struct sc_softc *, volatile struct sc_chan_stat *); 161 1.15 tsutsui static void sc_dio_pad(struct sc_softc *, volatile struct sc_chan_stat *); 162 1.15 tsutsui static void print_scsi_stat(struct sc_softc *); 163 1.15 tsutsui static void append_wb(struct sc_softc *, struct sc_chan_stat *); 164 1.15 tsutsui static struct sc_chan_stat *get_wb_chan(struct sc_softc *); 165 1.15 tsutsui static int release_wb(struct sc_softc *); 166 1.15 tsutsui static void adjust_transfer(struct sc_softc *, struct sc_chan_stat *); 167 1.15 tsutsui static void clean_k2dcache(struct sc_scb *); 168 1.1 tsubai 169 1.15 tsutsui extern void sc_done(struct sc_scb *); 170 1.15 tsutsui extern paddr_t kvtophys(vaddr_t); 171 1.1 tsubai 172 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 173 1.19 tsutsui #define dma_reset(x) do { \ 174 1.17 tsutsui int __s = splscsi(); \ 175 1.3 tsubai dmac_gsel = (x); dmac_cctl = DM_RST; dmac_cctl = 0; \ 176 1.17 tsutsui splx(__s); \ 177 1.19 tsutsui } while (/* CONSTCOND */ 0) 178 1.1 tsubai #endif 179 1.1 tsubai 180 1.1 tsubai int 181 1.15 tsutsui WAIT_STATR_BITCLR(int bitmask) 182 1.1 tsubai { 183 1.15 tsutsui int iloop; 184 1.19 tsutsui uint8_t dummy; 185 1.1 tsubai 186 1.1 tsubai iloop = 0; 187 1.1 tsubai do { 188 1.1 tsubai dummy = sc_statr; 189 1.1 tsubai DMAC_WAIT0; 190 1.1 tsubai if (iloop++ > CHECK_LOOP_CNT) 191 1.15 tsutsui return -1; 192 1.1 tsubai } while (dummy & bitmask); 193 1.15 tsutsui return 0; 194 1.1 tsubai } 195 1.1 tsubai 196 1.1 tsubai int 197 1.15 tsutsui WAIT_STATR_BITSET(int bitmask) 198 1.1 tsubai { 199 1.15 tsutsui int iloop; 200 1.19 tsutsui uint8_t dummy; 201 1.1 tsubai 202 1.1 tsubai iloop = 0; 203 1.1 tsubai do { 204 1.1 tsubai dummy = sc_statr; 205 1.1 tsubai DMAC_WAIT0; 206 1.1 tsubai if (iloop++ > CHECK_LOOP_CNT) 207 1.15 tsutsui return -1; 208 1.1 tsubai } while ((dummy & bitmask) == 0); 209 1.15 tsutsui return 0; 210 1.1 tsubai } 211 1.1 tsubai 212 1.1 tsubai void 213 1.15 tsutsui SET_CMD(struct sc_softc *sc, int CMD) 214 1.1 tsubai { 215 1.15 tsutsui 216 1.15 tsutsui (void)WAIT_STATR_BITCLR(R0_CIP); 217 1.15 tsutsui sc->lastcmd = CMD; 218 1.15 tsutsui sc_comr = CMD; 219 1.1 tsubai DMAC_WAIT0; 220 1.1 tsubai } 221 1.1 tsubai 222 1.1 tsubai void 223 1.15 tsutsui SET_CNT(int COUNT) 224 1.1 tsubai { 225 1.15 tsutsui 226 1.15 tsutsui sc_tclow = COUNT & 0xff; 227 1.1 tsubai DMAC_WAIT0; 228 1.15 tsutsui sc_tcmid = (COUNT >> 8) & 0xff; 229 1.1 tsubai DMAC_WAIT0; 230 1.15 tsutsui sc_tchi = (COUNT >> 16) & 0xff; 231 1.1 tsubai DMAC_WAIT0; 232 1.1 tsubai } 233 1.1 tsubai 234 1.1 tsubai int 235 1.15 tsutsui GET_CNT(void) 236 1.1 tsubai { 237 1.19 tsutsui int COUNT; 238 1.1 tsubai 239 1.1 tsubai COUNT = sc_tclow; 240 1.1 tsubai DMAC_WAIT0; 241 1.1 tsubai COUNT += (sc_tcmid << 8) & 0xff00; 242 1.1 tsubai DMAC_WAIT0; 243 1.1 tsubai COUNT += (sc_tchi << 16) & 0xff0000; 244 1.1 tsubai DMAC_WAIT0; 245 1.15 tsutsui return COUNT; 246 1.1 tsubai } 247 1.1 tsubai 248 1.1 tsubai void 249 1.19 tsutsui GET_INTR(uint8_t *DATA1, uint8_t *DATA2) 250 1.1 tsubai { 251 1.15 tsutsui 252 1.15 tsutsui (void)WAIT_STATR_BITCLR(R0_CIP); 253 1.1 tsubai while (sc_statr & R0_MIRQ) { 254 1.1 tsubai DMAC_WAIT0; 255 1.1 tsubai *DATA1 |= sc_intrq1; 256 1.1 tsubai DMAC_WAIT0; 257 1.1 tsubai *DATA2 |= sc_intrq2; 258 1.1 tsubai DMAC_WAIT0; 259 1.1 tsubai } 260 1.1 tsubai } 261 1.1 tsubai 262 1.1 tsubai 263 1.1 tsubai void 264 1.15 tsutsui sc_send(struct sc_scb *scb, int chan, int ie) 265 1.4 tsubai { 266 1.4 tsubai struct sc_softc *sc = scb->scb_softc; 267 1.4 tsubai struct sc_chan_stat *cs; 268 1.4 tsubai struct scsipi_xfer *xs; 269 1.4 tsubai int i; 270 1.19 tsutsui uint8_t *p; 271 1.4 tsubai 272 1.4 tsubai cs = &sc->chan_stat[chan]; 273 1.4 tsubai xs = scb->xs; 274 1.4 tsubai 275 1.19 tsutsui p = (uint8_t *)xs->cmd; 276 1.4 tsubai if (cs->scb != NULL) { 277 1.4 tsubai printf("SCSI%d: sc_send() NOT NULL cs->sc\n", chan); 278 1.16 christos printf("ie=0x%x scb=%p cs->sc=%p\n", ie, scb, cs->scb); 279 1.4 tsubai printf("cdb="); 280 1.4 tsubai for (i = 0; i < 6; i++) 281 1.4 tsubai printf(" 0x%x", *p++); 282 1.4 tsubai printf("\n"); 283 1.4 tsubai panic("SCSI soft error"); 284 1.1 tsubai /*NOTREACHED*/ 285 1.1 tsubai } 286 1.1 tsubai 287 1.4 tsubai if (p[0] == SCOP_RESET && p[1] == SCOP_RESET) { 288 1.1 tsubai /* 289 1.1 tsubai * SCSI bus reset command procedure 290 1.27 andvar * (vendor unique by Sony Corp.) 291 1.1 tsubai */ 292 1.1 tsubai #ifdef SCSI_1185AQ 293 1.4 tsubai if (sc_idenr & 0x08) 294 1.4 tsubai sc->scsi_1185AQ = 1; 295 1.4 tsubai else 296 1.4 tsubai sc->scsi_1185AQ = 0; 297 1.1 tsubai #endif 298 1.4 tsubai cs->scb = scb; 299 1.1 tsubai scsi_hardreset(); 300 1.4 tsubai scb->istatus = INST_EP; 301 1.4 tsubai cs->scb = NULL; 302 1.4 tsubai sc_done(scb); 303 1.1 tsubai return; 304 1.1 tsubai } 305 1.1 tsubai 306 1.4 tsubai if (scb->sc_map && (scb->sc_map->mp_pages > 0)) { 307 1.1 tsubai /* 308 1.1 tsubai * use map table 309 1.1 tsubai */ 310 1.4 tsubai scb->sc_coffset = scb->sc_map->mp_offset & PGOFSET; 311 1.4 tsubai if (scb->sc_map->mp_pages > NSCMAP) { 312 1.1 tsubai printf("SCSI%d: map table overflow\n", chan); 313 1.4 tsubai scb->istatus = INST_EP|INST_LB|INST_PRE; 314 1.1 tsubai return; 315 1.1 tsubai } 316 1.1 tsubai } else { 317 1.1 tsubai /* 318 1.1 tsubai * no use map table 319 1.1 tsubai */ 320 1.4 tsubai scb->sc_coffset = (u_int)scb->sc_cpoint & PGOFSET; 321 1.1 tsubai } 322 1.4 tsubai scb->sc_ctag = 0; 323 1.1 tsubai 324 1.4 tsubai cs->scb = scb; 325 1.1 tsubai cs->comflg = OFF; 326 1.1 tsubai 327 1.1 tsubai cs->intr_flg = ie; 328 1.1 tsubai cs->chan_num = chan; 329 1.4 tsubai sc->perr_flag[chan] = 0; 330 1.4 tsubai sc->mout_flag[chan] = 0; 331 1.4 tsubai sc->min_cnt[chan] = 0; 332 1.4 tsubai 333 1.4 tsubai sc->sel_stat[chan] = SEL_WAIT; 334 1.4 tsubai append_wb(sc, cs); 335 1.4 tsubai sc_start(sc); 336 1.1 tsubai } 337 1.1 tsubai 338 1.1 tsubai /* 339 1.1 tsubai * SCSI start up routine 340 1.1 tsubai */ 341 1.1 tsubai void 342 1.15 tsutsui sc_start(struct sc_softc *sc) 343 1.1 tsubai { 344 1.4 tsubai struct sc_chan_stat *cs; 345 1.19 tsutsui int chan, s; 346 1.19 tsutsui uint8_t dummy; 347 1.1 tsubai 348 1.4 tsubai s = splscsi(); 349 1.4 tsubai cs = get_wb_chan(sc); 350 1.4 tsubai if ((cs == NULL) || (sc->ipc >= 0)) 351 1.1 tsubai goto sc_start_exit; 352 1.4 tsubai chan = cs->chan_num; 353 1.4 tsubai if (sc->sel_stat[chan] != SEL_WAIT) { 354 1.1 tsubai /* 355 1.1 tsubai * already started 356 1.1 tsubai */ 357 1.1 tsubai goto sc_start_exit; 358 1.1 tsubai } 359 1.4 tsubai sc->sel_stat[chan] = SEL_START; 360 1.1 tsubai 361 1.1 tsubai dummy = sc_cmonr; 362 1.1 tsubai DMAC_WAIT0; 363 1.1 tsubai if (dummy & (R4_MBSY|R4_MSEL)) { 364 1.4 tsubai sc->sel_stat[chan] = SEL_WAIT; 365 1.1 tsubai goto sc_start_exit; 366 1.1 tsubai } 367 1.1 tsubai 368 1.1 tsubai /* 369 1.1 tsubai * send SELECT with ATN command 370 1.1 tsubai */ 371 1.4 tsubai sc->dma_stat = OFF; 372 1.4 tsubai sc->pad_start = 0; 373 1.1 tsubai dummy = sc_statr; 374 1.1 tsubai DMAC_WAIT0; 375 1.1 tsubai if (dummy & R0_CIP) { 376 1.4 tsubai sc->sel_stat[chan] = SEL_WAIT; 377 1.1 tsubai goto sc_start_exit; 378 1.1 tsubai } 379 1.1 tsubai sc_idenr = (chan << SC_TG_SHIFT) | SC_OWNID; 380 1.1 tsubai DMAC_WAIT0; 381 1.1 tsubai #ifdef SCSI_1185AQ 382 1.4 tsubai if (sc->scsi_1185AQ) 383 1.1 tsubai sc_intok1 = Ra_STO|Ra_ARBF; 384 1.1 tsubai else 385 1.1 tsubai sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF; 386 1.1 tsubai #else 387 1.1 tsubai sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF; 388 1.1 tsubai #endif 389 1.1 tsubai DMAC_WAIT0; 390 1.1 tsubai /* 391 1.1 tsubai * BUGFIX for signal reflection on BSY 392 1.1 tsubai * !Rb_DCNT 393 1.1 tsubai */ 394 1.1 tsubai sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE; 395 1.1 tsubai DMAC_WAIT0; 396 1.1 tsubai 397 1.1 tsubai dummy = sc_cmonr; 398 1.1 tsubai DMAC_WAIT0; 399 1.1 tsubai if (dummy & (R4_MBSY|R4_MSEL)) { 400 1.4 tsubai sc->sel_stat[chan] = SEL_WAIT; 401 1.1 tsubai goto sc_start_exit; 402 1.1 tsubai } 403 1.4 tsubai SET_CMD(sc, SCMD_SEL_ATN); 404 1.1 tsubai 405 1.1 tsubai sc_start_exit: 406 1.1 tsubai splx(s); 407 1.1 tsubai } 408 1.1 tsubai 409 1.1 tsubai /* 410 1.1 tsubai * SCSI interrupt service routine 411 1.1 tsubai */ 412 1.1 tsubai int 413 1.15 tsutsui scintr(void) 414 1.1 tsubai { 415 1.15 tsutsui int iloop; 416 1.19 tsutsui int chan; 417 1.19 tsutsui uint8_t dummy; 418 1.4 tsubai struct sc_softc *sc; 419 1.4 tsubai struct sc_chan_stat *cs; 420 1.19 tsutsui uint8_t s_int1, s_int2; 421 1.1 tsubai 422 1.19 tsutsui sc = device_lookup_private(&sc_cd, 0); /* XXX */ 423 1.4 tsubai 424 1.1 tsubai scintr_loop: 425 1.1 tsubai 426 1.1 tsubai #if defined(CHECK_MRQ) && defined(news3400) 427 1.1 tsubai while (dmac_gstat & CH_MRQ(CH_SCSI)) 428 1.1 tsubai DMAC_WAIT; 429 1.1 tsubai #endif 430 1.1 tsubai 431 1.1 tsubai for (iloop = 0; iloop < 100; iloop++) { 432 1.1 tsubai dummy = sc_statr; 433 1.1 tsubai DMAC_WAIT; 434 1.1 tsubai if ((dummy & R0_CIP) == 0) 435 1.1 tsubai break; 436 1.1 tsubai } 437 1.1 tsubai 438 1.1 tsubai /* 439 1.1 tsubai * get SCSI interrupt request 440 1.1 tsubai */ 441 1.1 tsubai while (sc_statr & R0_MIRQ) { 442 1.1 tsubai DMAC_WAIT0; 443 1.1 tsubai s_int1 = sc_intrq1; 444 1.1 tsubai DMAC_WAIT0; 445 1.1 tsubai s_int2 = sc_intrq2; 446 1.1 tsubai DMAC_WAIT0; 447 1.4 tsubai sc->int_stat1 |= s_int1; 448 1.4 tsubai sc->int_stat2 |= s_int2; 449 1.1 tsubai } 450 1.1 tsubai 451 1.4 tsubai if (sc->int_stat2 & R3_SRST) { 452 1.1 tsubai /* 453 1.26 andvar * RST signal is derived 454 1.1 tsubai */ 455 1.4 tsubai sc->int_stat2 &= ~R3_SRST; 456 1.4 tsubai scsi_softreset(sc); 457 1.1 tsubai goto scintr_exit; 458 1.1 tsubai } 459 1.1 tsubai 460 1.4 tsubai if ((sc->ipc < 0) && (sc->wrc <= 0) && (sc->wbc <= 0)) { 461 1.4 tsubai sc->int_stat1 = 0; 462 1.4 tsubai sc->int_stat2 = 0; 463 1.1 tsubai goto scintr_exit; 464 1.1 tsubai } 465 1.1 tsubai 466 1.4 tsubai cs = get_wb_chan(sc); 467 1.19 tsutsui if (cs) 468 1.19 tsutsui chan = cs->chan_num; 469 1.4 tsubai 470 1.4 tsubai if (cs && (sc->sel_stat[chan] == SEL_START) && 471 1.4 tsubai (sc->lastcmd == SCMD_SEL_ATN)) { 472 1.1 tsubai /* 473 1.1 tsubai * Check the result of SELECTION command 474 1.1 tsubai */ 475 1.4 tsubai if (sc->int_stat1 & R2_RSL) { 476 1.1 tsubai /* 477 1.1 tsubai * RESELECTION occur 478 1.1 tsubai */ 479 1.4 tsubai if (sc->wrc > 0) { 480 1.4 tsubai sc->sel_stat[chan] = SEL_RSLD; 481 1.1 tsubai } else { 482 1.1 tsubai /* 483 1.1 tsubai * Ghost RESELECTION ??? 484 1.1 tsubai */ 485 1.4 tsubai sc->int_stat1 &= ~R2_RSL; 486 1.1 tsubai } 487 1.1 tsubai } 488 1.4 tsubai if (sc->int_stat1 & R2_ARBF) { 489 1.1 tsubai /* 490 1.1 tsubai * ARBITRATION fault 491 1.1 tsubai */ 492 1.4 tsubai sc->int_stat1 &= ~R2_ARBF; 493 1.4 tsubai sc->sel_stat[chan] = SEL_ARBF; 494 1.1 tsubai } 495 1.4 tsubai if (sc->int_stat1 & R2_STO) { 496 1.1 tsubai /* 497 1.1 tsubai * SELECTION timeout 498 1.1 tsubai */ 499 1.4 tsubai sc->int_stat1 &= ~R2_STO; 500 1.15 tsutsui if ((sc->int_stat2&(R3_PHC|R3_RMSG)) != 501 1.15 tsutsui (R3_PHC|R3_RMSG)) { 502 1.4 tsubai sc->ipc = chan; 503 1.4 tsubai sc->ip = &sc->chan_stat[chan]; 504 1.4 tsubai sc->sel_stat[chan] = SEL_TIMEOUT; 505 1.4 tsubai sc->chan_stat[chan].scb->istatus 506 1.1 tsubai = INST_EP|INST_TO; 507 1.4 tsubai release_wb(sc); 508 1.1 tsubai } 509 1.1 tsubai } 510 1.1 tsubai 511 1.1 tsubai /* 512 1.1 tsubai * SELECTION command done 513 1.1 tsubai */ 514 1.4 tsubai switch (sc->sel_stat[chan]) { 515 1.1 tsubai 516 1.1 tsubai case SEL_START: 517 1.4 tsubai if ((sc->int_stat2 & R3_FNC) == 0) 518 1.1 tsubai break; 519 1.1 tsubai /* 520 1.1 tsubai * SELECTION success 521 1.1 tsubai */ 522 1.1 tsubai sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE; 523 1.4 tsubai sc->ipc = chan; 524 1.4 tsubai sc->ip = &sc->chan_stat[chan]; 525 1.4 tsubai sc->ip->scb->istatus |= INST_IP; 526 1.4 tsubai sc->dma_stat = OFF; 527 1.4 tsubai sc->pad_start = 0; 528 1.4 tsubai sc->sel_stat[chan] = SEL_SUCCESS; 529 1.4 tsubai release_wb(sc); 530 1.1 tsubai #ifndef NOT_SUPPORT_SYNCTR 531 1.4 tsubai sc_syncr = sc->sync_tr[chan]; 532 1.1 tsubai DMAC_WAIT0; 533 1.1 tsubai #endif 534 1.1 tsubai DMAC_WAIT0; 535 1.1 tsubai break; 536 1.1 tsubai 537 1.1 tsubai case SEL_TIMEOUT: 538 1.1 tsubai /* 539 1.1 tsubai * SELECTION time out 540 1.1 tsubai */ 541 1.4 tsubai sc_discon(sc); 542 1.1 tsubai goto scintr_exit; 543 1.1 tsubai 544 1.1 tsubai /* case SEL_RSLD: */ 545 1.1 tsubai /* case SEL_ARBF: */ 546 1.1 tsubai default: 547 1.1 tsubai /* 548 1.1 tsubai * SELECTION failed 549 1.1 tsubai */ 550 1.4 tsubai sc->sel_stat[chan] = SEL_WAIT; 551 1.1 tsubai break; 552 1.1 tsubai } 553 1.4 tsubai if ((sc->int_stat1 & R2_RSL) == 0) 554 1.4 tsubai sc->int_stat2 &= ~R3_FNC; 555 1.1 tsubai } 556 1.1 tsubai 557 1.4 tsubai if (sc->ip != NULL) { 558 1.1 tsubai /* 559 1.1 tsubai * check In Process channel's request 560 1.1 tsubai */ 561 1.4 tsubai if (sc->dma_stat != OFF) { 562 1.1 tsubai /* 563 1.1 tsubai * adjust pointer & counter 564 1.1 tsubai */ 565 1.4 tsubai adjust_transfer(sc, sc->ip); 566 1.1 tsubai } 567 1.4 tsubai if (sc->int_stat2 & R3_SPE) { 568 1.15 tsutsui int volatile statr; 569 1.15 tsutsui int volatile cmonr; 570 1.1 tsubai 571 1.1 tsubai statr = sc_statr; 572 1.21 christos __USE(statr); 573 1.1 tsubai DMAC_WAIT0; 574 1.1 tsubai cmonr = sc_cmonr; 575 1.21 christos __USE(cmonr); 576 1.4 tsubai sc->int_stat2 &= ~R3_SPE; 577 1.4 tsubai sc->perr_flag[sc->ip->chan_num] = 1; 578 1.1 tsubai } 579 1.1 tsubai } 580 1.1 tsubai 581 1.4 tsubai if (sc->int_stat2 & R3_DCNT) { 582 1.1 tsubai /* 583 1.1 tsubai * Bus Free 584 1.1 tsubai */ 585 1.4 tsubai sc_discon(sc); 586 1.4 tsubai sc->int_stat2 &= ~R3_DCNT; 587 1.1 tsubai } 588 1.1 tsubai 589 1.4 tsubai if ((sc->ipc >= 0) && (sc->sel_stat[sc->ipc] == SEL_RSL_WAIT)) { 590 1.4 tsubai sc->sel_stat[sc->ipc] = SEL_RSLD; 591 1.4 tsubai sc->ipc = -1; 592 1.4 tsubai sc->int_stat1 |= R2_RSL; 593 1.1 tsubai } 594 1.4 tsubai if (sc->int_stat1 & R2_RSL) { 595 1.1 tsubai /* 596 1.1 tsubai * Reselection 597 1.1 tsubai */ 598 1.4 tsubai sc_resel(sc); 599 1.4 tsubai sc->int_stat1 &= ~R2_RSL; 600 1.4 tsubai if (sc->sel_stat[sc->ipc] == SEL_RSL_WAIT) 601 1.1 tsubai goto scintr_exit; 602 1.1 tsubai } 603 1.1 tsubai 604 1.1 tsubai 605 1.4 tsubai if ((sc->ipc >= 0) && (sc->ipc != SC_OWNID) && 606 1.4 tsubai (sc->sel_stat[sc->ipc] == SEL_SUCCESS)) { 607 1.4 tsubai if (sc->int_stat2 & R3_PHC) { 608 1.1 tsubai /* 609 1.1 tsubai * Phase change 610 1.1 tsubai */ 611 1.4 tsubai sc->int_stat2 &= ~(R3_PHC|R3_RMSG); 612 1.4 tsubai sc_pmatch(sc); 613 1.4 tsubai } else if (sc->int_stat2 & R3_RMSG) { 614 1.1 tsubai /* 615 1.1 tsubai * message Phase 616 1.1 tsubai */ 617 1.4 tsubai if (sc->min_flag > 0) { 618 1.4 tsubai sc->int_stat2 &= ~(R3_PHC|R3_RMSG); 619 1.4 tsubai sc_pmatch(sc); 620 1.1 tsubai } 621 1.1 tsubai } 622 1.4 tsubai else if (sc->dma_stat != OFF) { 623 1.1 tsubai dummy = sc_cmonr; 624 1.1 tsubai DMAC_WAIT0; 625 1.1 tsubai if ((dummy & (R4_MMSG|R4_MCD|R4_MREQ)) == R4_MREQ) { 626 1.1 tsubai /* 627 1.1 tsubai * still DATA transfer phase 628 1.1 tsubai */ 629 1.4 tsubai sc_dio_pad(sc, sc->ip); 630 1.1 tsubai } 631 1.1 tsubai } 632 1.4 tsubai else if (sc->ip->comflg == CF_SEND) { 633 1.1 tsubai dummy = sc_cmonr; 634 1.1 tsubai DMAC_WAIT0; 635 1.1 tsubai if ((dummy & SC_PMASK) == COM_OUT) { 636 1.1 tsubai /* 637 1.1 tsubai * command out phase 638 1.1 tsubai */ 639 1.4 tsubai sc_cout(sc, sc->ip); 640 1.1 tsubai } 641 1.1 tsubai } 642 1.1 tsubai } else { 643 1.4 tsubai if (sc->int_stat2 & (R3_PHC|R3_RMSG)) 644 1.1 tsubai goto scintr_exit; 645 1.1 tsubai } 646 1.1 tsubai 647 1.4 tsubai if ((sc->int_stat1 & (R2_STO|R2_RSL|R2_ARBF)) 648 1.4 tsubai || (sc->int_stat2 & (R3_DCNT|R3_SRST|R3_PHC|R3_SPE))) { 649 1.1 tsubai /* 650 1.1 tsubai * still remain intrq 651 1.1 tsubai */ 652 1.1 tsubai goto scintr_loop; 653 1.1 tsubai } 654 1.1 tsubai 655 1.1 tsubai scintr_exit: 656 1.15 tsutsui return 1; 657 1.1 tsubai } 658 1.1 tsubai 659 1.1 tsubai /* 660 1.1 tsubai * SCSI bus reset routine 661 1.1 tsubai * scsi_hardreset() is occered a reset interrupt. 662 1.1 tsubai * And call scsi_softreset(). 663 1.1 tsubai */ 664 1.1 tsubai void 665 1.15 tsutsui scsi_hardreset(void) 666 1.1 tsubai { 667 1.15 tsutsui int s; 668 1.1 tsubai #ifdef DMAC_MAP_INIT 669 1.15 tsutsui int i; 670 1.1 tsubai #endif 671 1.4 tsubai struct sc_softc *sc; 672 1.1 tsubai 673 1.19 tsutsui sc = device_lookup_private(&sc_cd, 0); /* XXX */ 674 1.1 tsubai s = splscsi(); 675 1.1 tsubai 676 1.4 tsubai scsi_chipreset(sc); 677 1.1 tsubai DMAC_WAIT0; 678 1.4 tsubai sc->int_stat1 = 0; 679 1.4 tsubai sc->int_stat2 = 0; 680 1.4 tsubai SET_CMD(sc, SCMD_AST_RST); /* assert RST signal */ 681 1.1 tsubai 682 1.1 tsubai #ifdef DMAC_MAP_INIT 683 1.1 tsubai if (dmac_map_init == 0) { 684 1.1 tsubai dmac_map_init++; 685 1.1 tsubai for (i = 0; i < NDMACMAP; i++) { 686 1.9 thorpej # if defined(__mips__) && defined(CPU_SINGLE) 687 1.1 tsubai dmac_gsel = CH_SCSI; 688 1.19 tsutsui dmac_ctag = (uint8_t)i; 689 1.19 tsutsui dmac_cmap = (uint16_t)0; 690 1.1 tsubai # endif 691 1.1 tsubai } 692 1.1 tsubai } 693 1.1 tsubai #endif 694 1.1 tsubai /*cxd1185_init();*/ 695 1.1 tsubai splx(s); 696 1.1 tsubai } 697 1.1 tsubai 698 1.1 tsubai /* 699 1.1 tsubai * I/O port (sc_ioptr) bit assign 700 1.11 tsutsui * 701 1.1 tsubai * Rf_PRT3 - <reserved> 702 1.1 tsubai * Rf_PRT2 - <reserved> 703 1.1 tsubai * Rf_PRT1 out Floppy Disk Density control 704 1.1 tsubai * Rf_PRT0 out Floppy Disk Eject control 705 1.1 tsubai */ 706 1.1 tsubai 707 1.1 tsubai void 708 1.15 tsutsui scsi_chipreset(struct sc_softc *sc) 709 1.1 tsubai { 710 1.15 tsutsui int s; 711 1.19 tsutsui uint8_t save_ioptr; 712 1.1 tsubai 713 1.1 tsubai s = splscsi(); 714 1.1 tsubai 715 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 716 1.1 tsubai dmac_gsel = CH_SCSI; 717 1.1 tsubai dmac_cwid = 4; /* initialize DMAC SCSI chan */ 718 1.19 tsutsui *(volatile uint8_t *)PINTEN |= DMA_INTEN; 719 1.1 tsubai dma_reset(CH_SCSI); 720 1.1 tsubai #endif 721 1.1 tsubai sc_envir = 0; /* 1/4 clock */ 722 1.1 tsubai DMAC_WAIT0; 723 1.1 tsubai save_ioptr = sc_ioptr; 724 1.1 tsubai DMAC_WAIT0; 725 1.4 tsubai sc->lastcmd = SCMD_CHIP_RST; 726 1.1 tsubai sc_comr = SCMD_CHIP_RST; /* reset chip */ 727 1.1 tsubai DMAC_WAIT; 728 1.15 tsutsui (void)WAIT_STATR_BITCLR(R0_CIP); 729 1.1 tsubai /* 730 1.1 tsubai * SCMD_CHIP_RST command reset all register 731 1.1 tsubai * except sc_statr<7:6> & sc_cmonr. 732 1.1 tsubai * So, bit R0_MIRQ & R3_FNC will be not set. 733 1.1 tsubai */ 734 1.1 tsubai sc_idenr = SC_OWNID; 735 1.1 tsubai DMAC_WAIT0; 736 1.1 tsubai 737 1.1 tsubai sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF; 738 1.1 tsubai DMAC_WAIT0; 739 1.1 tsubai sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG; 740 1.1 tsubai DMAC_WAIT0; 741 1.1 tsubai 742 1.1 tsubai sc_ioptr = save_ioptr; 743 1.1 tsubai DMAC_WAIT; 744 1.1 tsubai 745 1.1 tsubai sc_moder = Rc_TMSL; /* RST drive time = 25.5 us */ 746 1.1 tsubai DMAC_WAIT0; 747 1.1 tsubai sc_timer = 0x2; 748 1.1 tsubai DMAC_WAIT0; 749 1.1 tsubai 750 1.1 tsubai sc_moder = Rc_SPHI; /* selection timeout = 252 ms */ 751 1.1 tsubai DMAC_WAIT0; 752 1.1 tsubai sc_timer = SEL_TIMEOUT_VALUE; 753 1.1 tsubai DMAC_WAIT0; 754 1.1 tsubai 755 1.1 tsubai #ifdef SCSI_1185AQ 756 1.4 tsubai if (sc->scsi_1185AQ) 757 1.4 tsubai SET_CMD(sc, SCMD_ENB_SEL); /* enable reselection */ 758 1.1 tsubai #endif 759 1.1 tsubai 760 1.4 tsubai sc->int_stat1 &= ~R2_RSL; /* ignore RSL inter request */ 761 1.1 tsubai 762 1.1 tsubai splx(s); 763 1.1 tsubai } 764 1.1 tsubai 765 1.1 tsubai void 766 1.15 tsutsui scsi_softreset(struct sc_softc *sc) 767 1.1 tsubai { 768 1.19 tsutsui struct sc_chan_stat *cs; 769 1.4 tsubai int i; 770 1.15 tsutsui /* int (*handler)(); */ 771 1.1 tsubai 772 1.4 tsubai sc->wbq_actf = NULL; 773 1.4 tsubai sc->wbq_actl = NULL; 774 1.4 tsubai sc->wbc = 0; 775 1.4 tsubai sc->wrc = 0; 776 1.4 tsubai sc->ip = NULL; 777 1.4 tsubai sc->ipc = -1; 778 1.4 tsubai sc->dma_stat = OFF; 779 1.4 tsubai sc->pad_start = 0; 780 1.1 tsubai 781 1.1 tsubai for (i = 0; i < NTARGET; ++i) { 782 1.1 tsubai if (i == SC_OWNID) 783 1.1 tsubai continue; 784 1.4 tsubai cs = &sc->chan_stat[i]; 785 1.1 tsubai cs->wb_next = NULL; 786 1.1 tsubai #ifndef NOT_SUPPORT_SYNCTR 787 1.4 tsubai sc->sync_tr[i] = 0; /* asynchronous mode */ 788 1.1 tsubai #endif 789 1.4 tsubai sc->sel_stat[i] = SEL_WAIT; 790 1.4 tsubai if (cs->scb != NULL) { 791 1.4 tsubai struct sc_scb *scb = cs->scb; 792 1.4 tsubai 793 1.4 tsubai if ((cs->scb->istatus & INST_EP) == 0) 794 1.4 tsubai cs->scb->istatus = (INST_EP|INST_HE); 795 1.4 tsubai cs->scb = NULL; 796 1.9 thorpej #ifdef __mips__ 797 1.4 tsubai clean_k2dcache(scb); 798 1.4 tsubai #endif 799 1.4 tsubai if (cs->intr_flg == SCSI_INTEN) { 800 1.4 tsubai intrcnt[SCSI_INTR]++; 801 1.1 tsubai #if 0 802 1.4 tsubai handler = scintsw[i].sci_inthandler; 803 1.4 tsubai if (handler) 804 1.4 tsubai (*handler)(scintsw[i].sci_ctlr); 805 1.1 tsubai #endif 806 1.1 tsubai } 807 1.4 tsubai sc_done(scb); 808 1.1 tsubai } 809 1.1 tsubai } 810 1.1 tsubai } 811 1.1 tsubai 812 1.1 tsubai /* 813 1.1 tsubai * RESELECTION interrupt service routine 814 1.1 tsubai * ( RESELECTION phase ) 815 1.1 tsubai */ 816 1.1 tsubai void 817 1.15 tsutsui sc_resel(struct sc_softc *sc) 818 1.1 tsubai { 819 1.15 tsutsui struct sc_chan_stat *cs; 820 1.19 tsutsui uint8_t chan; 821 1.19 tsutsui uint8_t statr; 822 1.15 tsutsui int iloop; 823 1.1 tsubai 824 1.4 tsubai sc->min_flag = 0; 825 1.1 tsubai chan = (sc_idenr & R6_SID_MASK) >> SC_TG_SHIFT; 826 1.1 tsubai 827 1.1 tsubai if (chan == SC_OWNID) 828 1.1 tsubai return; 829 1.1 tsubai 830 1.1 tsubai statr = sc_statr; 831 1.1 tsubai DMAC_WAIT0; 832 1.1 tsubai if (statr & R0_CIP) { 833 1.4 tsubai if (sc->lastcmd == SCMD_SEL_ATN) { 834 1.1 tsubai /* 835 1.1 tsubai * SELECTION command dead lock ? 836 1.1 tsubai * save interrupt request 837 1.1 tsubai */ 838 1.1 tsubai while (sc_statr & R0_MIRQ) { 839 1.1 tsubai DMAC_WAIT0; 840 1.4 tsubai sc->int_stat1 |= sc_intrq1; 841 1.1 tsubai DMAC_WAIT0; 842 1.4 tsubai sc->int_stat2 |= sc_intrq2; 843 1.1 tsubai DMAC_WAIT0; 844 1.1 tsubai } 845 1.4 tsubai scsi_chipreset(sc); 846 1.1 tsubai } 847 1.1 tsubai } 848 1.1 tsubai 849 1.4 tsubai cs = &sc->chan_stat[chan]; 850 1.4 tsubai if (cs->scb == NULL) { 851 1.1 tsubai scsi_hardreset(); 852 1.1 tsubai return; 853 1.1 tsubai } 854 1.4 tsubai if ((cs->scb->istatus & INST_WR) == 0) { 855 1.1 tsubai scsi_hardreset(); 856 1.1 tsubai return; 857 1.1 tsubai } 858 1.1 tsubai 859 1.4 tsubai if (sc->ipc >= 0) { 860 1.1 tsubai scsi_hardreset(); 861 1.1 tsubai return; 862 1.1 tsubai } 863 1.1 tsubai 864 1.4 tsubai sc->ip = cs; 865 1.4 tsubai sc->ipc = chan; 866 1.1 tsubai 867 1.1 tsubai sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE; 868 1.1 tsubai DMAC_WAIT0; 869 1.1 tsubai 870 1.1 tsubai iloop = 0; 871 1.4 tsubai while ((sc->int_stat2 & R3_FNC) == 0) { 872 1.1 tsubai /* 873 1.1 tsubai * Max 6 usec wait 874 1.1 tsubai */ 875 1.1 tsubai if (iloop++ > RSL_LOOP_CNT) { 876 1.4 tsubai sc->sel_stat[chan] = SEL_RSL_WAIT; 877 1.1 tsubai return; 878 1.1 tsubai } 879 1.4 tsubai GET_INTR(&sc->int_stat1, &sc->int_stat2); 880 1.1 tsubai } 881 1.4 tsubai sc->int_stat2 &= ~R3_FNC; 882 1.11 tsutsui 883 1.4 tsubai sc->sel_stat[chan] = SEL_SUCCESS; 884 1.1 tsubai 885 1.4 tsubai sc->wrc--; 886 1.4 tsubai sc->dma_stat = OFF; 887 1.4 tsubai sc->pad_start = 0; 888 1.4 tsubai cs->scb->istatus |= INST_IP; 889 1.4 tsubai cs->scb->istatus &= ~INST_WR; 890 1.1 tsubai 891 1.1 tsubai #ifndef NOT_SUPPORT_SYNCTR 892 1.4 tsubai sc_syncr = sc->sync_tr[chan]; 893 1.1 tsubai DMAC_WAIT0; 894 1.1 tsubai #endif 895 1.1 tsubai } 896 1.1 tsubai 897 1.1 tsubai /* 898 1.1 tsubai * DISCONNECT interrupt service routine 899 1.1 tsubai * ( Target disconnect / job done ) 900 1.1 tsubai */ 901 1.1 tsubai void 902 1.15 tsutsui sc_discon(struct sc_softc *sc) 903 1.1 tsubai { 904 1.19 tsutsui struct sc_chan_stat *cs; 905 1.15 tsutsui /* int (*handler)(); */ 906 1.19 tsutsui uint8_t dummy; 907 1.1 tsubai 908 1.1 tsubai /* 909 1.7 wiz * Signal reflection on BSY has occurred. 910 1.1 tsubai * Not Bus Free Phase, ignore. 911 1.1 tsubai * 912 1.1 tsubai * But, CXD1185Q reset INIT bit of sc_statr. 913 1.1 tsubai * So, can't issue Transfer Information command. 914 1.11 tsutsui * 915 1.1 tsubai * What shall we do ? Bus reset ? 916 1.1 tsubai */ 917 1.4 tsubai if ((sc->int_stat2 & R3_DCNT) && ((sc_intok2 & Rb_DCNT) == 0)) 918 1.1 tsubai return; 919 1.1 tsubai 920 1.1 tsubai sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE; 921 1.1 tsubai DMAC_WAIT0; 922 1.1 tsubai 923 1.4 tsubai sc->min_flag = 0; 924 1.1 tsubai dummy = sc_cmonr; 925 1.1 tsubai DMAC_WAIT0; 926 1.1 tsubai if (dummy & R4_MATN) { 927 1.4 tsubai SET_CMD(sc, SCMD_NGT_ATN); 928 1.1 tsubai (void) WAIT_STATR_BITSET(R0_MIRQ); 929 1.4 tsubai GET_INTR(&sc->int_stat1, &sc->int_stat2); /* clear interrupt */ 930 1.1 tsubai } 931 1.1 tsubai 932 1.4 tsubai if ((sc->int_stat1 & R2_RSL) == 0) 933 1.4 tsubai sc->int_stat2 &= ~R3_FNC; 934 1.1 tsubai 935 1.4 tsubai cs = sc->ip; 936 1.4 tsubai if ((cs == NULL) || (sc->ipc < 0)) 937 1.1 tsubai goto sc_discon_exit; 938 1.1 tsubai 939 1.4 tsubai if ((sc->sel_stat[cs->chan_num] != SEL_SUCCESS) 940 1.4 tsubai && (sc->sel_stat[cs->chan_num] != SEL_TIMEOUT)) 941 1.19 tsutsui printf("%s: eh!\n", __func__); 942 1.1 tsubai 943 1.1 tsubai /* 944 1.1 tsubai * indicate abnormal terminate 945 1.1 tsubai */ 946 1.4 tsubai if ((cs->scb->istatus & (INST_EP|INST_WR)) == 0) 947 1.4 tsubai cs->scb->istatus |= (INST_EP|INST_PRE|INST_LB); 948 1.1 tsubai 949 1.4 tsubai cs->scb->istatus &= ~INST_IP; 950 1.4 tsubai sc->dma_stat = OFF; 951 1.4 tsubai sc->pad_start = 0; 952 1.4 tsubai sc->ip = NULL; 953 1.4 tsubai sc->ipc = -1; 954 1.4 tsubai 955 1.4 tsubai if ((cs->scb->istatus & INST_WR) == 0) { 956 1.4 tsubai struct sc_scb *scb = cs->scb; 957 1.4 tsubai 958 1.4 tsubai if (sc->perr_flag[cs->chan_num] > 0) 959 1.4 tsubai cs->scb->istatus |= INST_EP|INST_PRE; 960 1.4 tsubai cs->scb = NULL; 961 1.9 thorpej #ifdef __mips__ 962 1.4 tsubai clean_k2dcache(scb); 963 1.4 tsubai #endif 964 1.4 tsubai if (cs->intr_flg == SCSI_INTEN) { 965 1.4 tsubai intrcnt[SCSI_INTR]++; 966 1.1 tsubai #if 0 967 1.4 tsubai handler = scintsw[cs->chan_num].sci_inthandler; 968 1.4 tsubai if (handler) 969 1.4 tsubai (*handler)(scintsw[cs->chan_num].sci_ctlr); 970 1.1 tsubai #endif 971 1.1 tsubai } 972 1.4 tsubai sc_done(scb); 973 1.1 tsubai } 974 1.1 tsubai 975 1.1 tsubai sc_discon_exit: 976 1.4 tsubai sc_start(sc); 977 1.1 tsubai } 978 1.1 tsubai 979 1.1 tsubai /* 980 1.1 tsubai * SCSI phase match interrupt service routine 981 1.1 tsubai */ 982 1.1 tsubai void 983 1.15 tsutsui sc_pmatch(struct sc_softc *sc) 984 1.1 tsubai { 985 1.4 tsubai struct sc_chan_stat *cs; 986 1.19 tsutsui uint8_t phase; 987 1.19 tsutsui uint8_t phase2; 988 1.19 tsutsui uint8_t cmonr; 989 1.1 tsubai 990 1.4 tsubai sc->int_stat2 &= ~R3_FNC; /* XXXXXXXX */ 991 1.1 tsubai 992 1.4 tsubai cs = sc->ip; 993 1.1 tsubai if (cs == NULL) 994 1.1 tsubai return; 995 1.1 tsubai 996 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 997 1.1 tsubai dma_reset(CH_SCSI); 998 1.4 tsubai #endif 999 1.1 tsubai phase = sc_cmonr & SC_PMASK; 1000 1.1 tsubai DMAC_WAIT0; 1001 1.1 tsubai for (;;) { 1002 1.1 tsubai phase2 = phase; 1003 1.1 tsubai cmonr = sc_cmonr; 1004 1.1 tsubai DMAC_WAIT0; 1005 1.1 tsubai phase = cmonr & SC_PMASK; 1006 1.1 tsubai if (phase == phase2) { 1007 1.1 tsubai if ((phase == DAT_IN) || (phase == DAT_OUT)) 1008 1.1 tsubai break; 1009 1.1 tsubai else if (cmonr & R4_MREQ) 1010 1.1 tsubai break; 1011 1.1 tsubai } 1012 1.1 tsubai } 1013 1.1 tsubai 1014 1.1 tsubai 1015 1.4 tsubai sc->dma_stat = OFF; 1016 1.4 tsubai sc->pad_start = 0; 1017 1.1 tsubai 1018 1.1 tsubai if (phase == COM_OUT) { 1019 1.4 tsubai sc->min_flag = 0; 1020 1.1 tsubai if (cs->comflg != CF_SEND) 1021 1.1 tsubai cs->comflg = CF_SET; 1022 1.4 tsubai sc_cout(sc, cs); 1023 1.1 tsubai } else { 1024 1.1 tsubai cs->comflg = CF_ENOUGH; 1025 1.1 tsubai sc_intok2 &= ~Rb_FNC; 1026 1.1 tsubai if (phase == MES_IN) { 1027 1.4 tsubai sc->min_flag++; 1028 1.4 tsubai sc_min(sc, cs); 1029 1.1 tsubai } else { 1030 1.4 tsubai sc->min_flag = 0; 1031 1.1 tsubai 1032 1.1 tsubai switch (phase) { 1033 1.1 tsubai 1034 1.1 tsubai case MES_OUT: 1035 1.4 tsubai sc_mout(sc, cs); 1036 1.1 tsubai break; 1037 1.1 tsubai 1038 1.1 tsubai case DAT_IN: 1039 1.1 tsubai case DAT_OUT: 1040 1.4 tsubai sc_dio(sc, cs); 1041 1.1 tsubai break; 1042 1.1 tsubai 1043 1.1 tsubai case STAT_IN: 1044 1.4 tsubai sc_sin(sc, cs); 1045 1.1 tsubai break; 1046 1.1 tsubai 1047 1.1 tsubai default: 1048 1.1 tsubai printf("SCSI%d: unknown phase\n", cs->chan_num); 1049 1.1 tsubai break; 1050 1.1 tsubai } 1051 1.1 tsubai } 1052 1.1 tsubai } 1053 1.1 tsubai } 1054 1.1 tsubai 1055 1.1 tsubai 1056 1.1 tsubai void 1057 1.15 tsutsui flush_fifo(struct sc_softc *sc) 1058 1.1 tsubai { 1059 1.19 tsutsui uint8_t dummy; 1060 1.19 tsutsui uint8_t tmp; 1061 1.19 tsutsui uint8_t tmp0; 1062 1.1 tsubai 1063 1.1 tsubai dummy = sc_ffstr; 1064 1.1 tsubai DMAC_WAIT0; 1065 1.1 tsubai if (dummy & R5_FIFOREM) { 1066 1.1 tsubai /* 1067 1.1 tsubai * flush FIFO 1068 1.1 tsubai */ 1069 1.4 tsubai SET_CMD(sc, SCMD_FLSH_FIFO); 1070 1.1 tsubai tmp = 0; 1071 1.1 tsubai do { 1072 1.1 tsubai do { 1073 1.1 tsubai dummy = sc_statr; 1074 1.1 tsubai DMAC_WAIT0; 1075 1.1 tsubai } while (dummy & R0_CIP); 1076 1.1 tsubai GET_INTR(&tmp0, &tmp); /* clear interrupt */ 1077 1.1 tsubai } while ((tmp & R3_FNC) == 0); 1078 1.1 tsubai } 1079 1.1 tsubai } 1080 1.1 tsubai 1081 1.1 tsubai /* 1082 1.1 tsubai * SCSI command send routine 1083 1.1 tsubai */ 1084 1.1 tsubai void 1085 1.15 tsutsui sc_cout(struct sc_softc *sc, struct sc_chan_stat *cs) 1086 1.1 tsubai { 1087 1.15 tsutsui int iloop; 1088 1.15 tsutsui int cdb_bytes; 1089 1.19 tsutsui uint8_t dummy; 1090 1.19 tsutsui uint8_t statr; 1091 1.4 tsubai struct scsipi_xfer *xs; 1092 1.1 tsubai 1093 1.1 tsubai if (cs->comflg == CF_SET) { 1094 1.4 tsubai struct sc_scb *scb = cs->scb; 1095 1.4 tsubai 1096 1.1 tsubai cs->comflg = CF_SEND; 1097 1.1 tsubai 1098 1.4 tsubai flush_fifo(sc); 1099 1.1 tsubai 1100 1.4 tsubai xs = scb->xs; 1101 1.4 tsubai cdb_bytes = xs->cmdlen; 1102 1.4 tsubai 1103 1.4 tsubai switch (xs->cmd->opcode & CMD_TYPEMASK) { 1104 1.1 tsubai case CMD_T0: 1105 1.1 tsubai case CMD_T1: 1106 1.1 tsubai case CMD_T5: 1107 1.1 tsubai break; 1108 1.1 tsubai 1109 1.1 tsubai default: 1110 1.1 tsubai cdb_bytes = 6; 1111 1.1 tsubai sc_intok2 |= Rb_FNC; 1112 1.1 tsubai break; 1113 1.1 tsubai } 1114 1.1 tsubai 1115 1.1 tsubai /* 1116 1.1 tsubai * set Active pointers 1117 1.1 tsubai */ 1118 1.4 tsubai sc->act_cmd_pointer = (char *)xs->cmd; 1119 1.4 tsubai cs->act_trcnt = scb->sc_ctrnscnt; 1120 1.4 tsubai cs->act_point = scb->sc_cpoint; 1121 1.4 tsubai cs->act_tag = scb->sc_ctag; 1122 1.4 tsubai cs->act_offset = scb->sc_coffset; 1123 1.1 tsubai 1124 1.1 tsubai } else { 1125 1.1 tsubai cdb_bytes = 1; 1126 1.1 tsubai iloop = 0; 1127 1.1 tsubai do { 1128 1.1 tsubai dummy = sc_cmonr; 1129 1.1 tsubai DMAC_WAIT0; 1130 1.1 tsubai if ((dummy & SC_PMASK) != COM_OUT) 1131 1.1 tsubai return; 1132 1.1 tsubai statr = sc_statr; 1133 1.1 tsubai DMAC_WAIT0; 1134 1.1 tsubai if (statr & R0_MIRQ) 1135 1.1 tsubai return; 1136 1.1 tsubai } while ((dummy & R4_MREQ) == 0); 1137 1.1 tsubai statr = sc_statr; 1138 1.1 tsubai DMAC_WAIT0; 1139 1.1 tsubai if (statr & R0_MIRQ) 1140 1.1 tsubai return; 1141 1.1 tsubai } 1142 1.1 tsubai 1143 1.1 tsubai 1144 1.1 tsubai SET_CNT(cdb_bytes); 1145 1.4 tsubai SET_CMD(sc, SCMD_TR_INFO|R0_TRBE); 1146 1.1 tsubai 1147 1.1 tsubai for (iloop = 0; iloop < cdb_bytes; iloop++) { 1148 1.1 tsubai do { 1149 1.1 tsubai dummy = sc_cmonr; 1150 1.1 tsubai DMAC_WAIT0; 1151 1.1 tsubai if ((dummy & SC_PMASK) != COM_OUT) 1152 1.1 tsubai return; 1153 1.1 tsubai } while ((dummy & R4_MREQ) == 0); 1154 1.1 tsubai statr = sc_statr; 1155 1.1 tsubai DMAC_WAIT0; 1156 1.1 tsubai if (statr & R0_MIRQ) 1157 1.1 tsubai return; 1158 1.4 tsubai sc_datr = *sc->act_cmd_pointer++; 1159 1.1 tsubai do { 1160 1.1 tsubai dummy = sc_cmonr; 1161 1.1 tsubai DMAC_WAIT0; 1162 1.1 tsubai } while ((dummy & R4_MACK) != 0); 1163 1.1 tsubai } 1164 1.1 tsubai } 1165 1.1 tsubai 1166 1.1 tsubai #define GET_MIN_COUNT 127 1167 1.1 tsubai 1168 1.1 tsubai /* 1169 1.1 tsubai * SCSI message accept routine 1170 1.1 tsubai */ 1171 1.1 tsubai void 1172 1.15 tsutsui sc_min(struct sc_softc *sc, struct sc_chan_stat *cs) 1173 1.1 tsubai { 1174 1.4 tsubai struct sc_scb *scb = cs->scb; 1175 1.4 tsubai struct scsipi_xfer *xs = scb->xs; 1176 1.19 tsutsui uint8_t dummy; 1177 1.1 tsubai 1178 1.1 tsubai sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG; 1179 1.1 tsubai DMAC_WAIT0; 1180 1.1 tsubai 1181 1.4 tsubai if (sc->min_flag == 1) 1182 1.4 tsubai flush_fifo(sc); 1183 1.1 tsubai 1184 1.1 tsubai dummy = sc_cmonr; 1185 1.1 tsubai DMAC_WAIT0; 1186 1.1 tsubai if ((dummy & R4_MREQ) == 0) { 1187 1.1 tsubai printf("sc_min: !REQ cmonr=%x\n", dummy); 1188 1.4 tsubai print_scsi_stat(sc); 1189 1.1 tsubai scsi_hardreset(); 1190 1.1 tsubai return; 1191 1.1 tsubai } 1192 1.1 tsubai 1193 1.1 tsubai /* retry_cmd_issue: */ 1194 1.4 tsubai sc->int_stat2 &= ~R3_FNC; 1195 1.4 tsubai SET_CMD(sc, SCMD_TR_INFO); 1196 1.1 tsubai do { 1197 1.1 tsubai do { 1198 1.1 tsubai dummy = sc_statr; 1199 1.1 tsubai DMAC_WAIT0; 1200 1.1 tsubai } while (dummy & R0_CIP); 1201 1.19 tsutsui GET_INTR(&sc->int_stat1, &sc->int_stat2); /* clear interrupt */ 1202 1.4 tsubai } while ((sc->int_stat2 & R3_FNC) == 0); 1203 1.4 tsubai sc->int_stat2 &= ~R3_FNC; 1204 1.1 tsubai 1205 1.1 tsubai dummy = sc_ffstr; 1206 1.1 tsubai if (dummy & R5_FIE) { 1207 1.1 tsubai DMAC_WAIT; 1208 1.1 tsubai dummy = sc_ffstr; 1209 1.1 tsubai DMAC_WAIT0; 1210 1.1 tsubai if (dummy & R5_FIE) { 1211 1.1 tsubai dummy = sc_statr; 1212 1.1 tsubai DMAC_WAIT0; 1213 1.1 tsubai if ((dummy & R0_INIT) == 0) { 1214 1.1 tsubai /* 1215 1.1 tsubai * CXD1185 detect BSY false 1216 1.1 tsubai */ 1217 1.1 tsubai scsi_hardreset(); 1218 1.1 tsubai return; 1219 1.1 tsubai } 1220 1.1 tsubai } 1221 1.1 tsubai } 1222 1.1 tsubai dummy = sc_datr; /* get message byte */ 1223 1.1 tsubai DMAC_WAIT0; 1224 1.1 tsubai 1225 1.4 tsubai if (sc->min_cnt[cs->chan_num] == 0) { 1226 1.4 tsubai scb->message = scb->identify; 1227 1.1 tsubai if (dummy == MSG_EXTND) { 1228 1.1 tsubai /* Extended Message */ 1229 1.4 tsubai sc->min_cnt[cs->chan_num] = GET_MIN_COUNT; 1230 1.4 tsubai sc->min_point[cs->chan_num] = scb->msgbuf; 1231 1.19 tsutsui memset(scb->msgbuf, 0, 8); 1232 1.4 tsubai *sc->min_point[cs->chan_num]++ = dummy; 1233 1.1 tsubai } else { 1234 1.1 tsubai switch ((dummy & MSG_IDENT)? MSG_IDENT : dummy) { 1235 1.1 tsubai 1236 1.1 tsubai case MSG_CCOMP: 1237 1.4 tsubai scb->istatus |= INST_EP; 1238 1.1 tsubai break; 1239 1.1 tsubai 1240 1.1 tsubai case MSG_MREJ: 1241 1.1 tsubai #ifndef NOT_SUPPORT_SYNCTR 1242 1.4 tsubai if (sc->mout_flag[cs->chan_num] == MOUT_SYNC_TR) 1243 1.4 tsubai sc->sync_tr[cs->chan_num] = 0; 1244 1.1 tsubai #endif 1245 1.1 tsubai break; 1246 1.1 tsubai 1247 1.1 tsubai case MSG_IDENT: 1248 1.1 tsubai case MSG_RDP: 1249 1.4 tsubai 1250 1.4 tsubai sc->dma_stat = OFF; 1251 1.4 tsubai sc->pad_start = 0; 1252 1.1 tsubai cs->comflg = OFF; 1253 1.1 tsubai /* 1254 1.4 tsubai * restore the saved value to Active pointers 1255 1.4 tsubai */ 1256 1.4 tsubai sc->act_cmd_pointer = (char *)xs->cmd; 1257 1.4 tsubai cs->act_trcnt = scb->sc_ctrnscnt; 1258 1.4 tsubai cs->act_point = scb->sc_cpoint; 1259 1.4 tsubai cs->act_tag = scb->sc_ctag; 1260 1.4 tsubai cs->act_offset = scb->sc_coffset; 1261 1.1 tsubai break; 1262 1.1 tsubai 1263 1.1 tsubai case MSG_SDP: 1264 1.1 tsubai /* 1265 1.1 tsubai * save Active pointers 1266 1.1 tsubai */ 1267 1.4 tsubai scb->sc_ctrnscnt = cs->act_trcnt; 1268 1.4 tsubai scb->sc_ctag = cs->act_tag; 1269 1.4 tsubai scb->sc_coffset = cs->act_offset; 1270 1.4 tsubai scb->sc_cpoint = cs->act_point; 1271 1.1 tsubai break; 1272 1.1 tsubai 1273 1.1 tsubai case MSG_DCNT: 1274 1.4 tsubai scb->istatus |= INST_WR; 1275 1.4 tsubai sc->wrc++; 1276 1.1 tsubai break; 1277 1.1 tsubai 1278 1.1 tsubai default: 1279 1.4 tsubai scb->message = MSG_MREJ; 1280 1.4 tsubai SET_CMD(sc, SCMD_AST_ATN); 1281 1.1 tsubai printf("SCSI%d:sc_min() Unknown mes=0x%x, \n", 1282 1.1 tsubai cs->chan_num, dummy); 1283 1.1 tsubai } 1284 1.1 tsubai } 1285 1.1 tsubai } else { 1286 1.4 tsubai *sc->min_point[cs->chan_num]++ = dummy; 1287 1.4 tsubai if (sc->min_cnt[cs->chan_num] == GET_MIN_COUNT) 1288 1.4 tsubai sc->min_cnt[cs->chan_num] = dummy; 1289 1.1 tsubai else 1290 1.4 tsubai sc->min_cnt[cs->chan_num]--; 1291 1.4 tsubai if (sc->min_cnt[cs->chan_num] <= 0) { 1292 1.1 tsubai #ifdef ABORT_SYNCTR_MES_FROM_TARGET 1293 1.4 tsubai if ((scb->msgbuf[2] == 0x01) && 1294 1.4 tsubai (sc->mout_flag[cs->chan_num] == MOUT_SYNC_TR)) { 1295 1.1 tsubai #else 1296 1.4 tsubai if (scb->msgbuf[2] == 0x01) { 1297 1.1 tsubai #endif 1298 1.15 tsutsui int i; 1299 1.1 tsubai /* 1300 1.1 tsubai * receive Synchronous transfer message reply 1301 1.1 tsubai * calculate transfer period val 1302 1.1 tsubai * tpm * 4/1000 us = 4/16 * (tpv + 1) 1303 1.1 tsubai */ 1304 1.1 tsubai #define TPM2TPV(tpm) (((tpm)*16 + 999) / 1000 - 1) 1305 1.1 tsubai #ifndef NOT_SUPPORT_SYNCTR 1306 1.4 tsubai i = scb->msgbuf[3]; /* get tpm */ 1307 1.1 tsubai i = TPM2TPV(i) << 4; 1308 1.4 tsubai if (scb->msgbuf[4] == 0) 1309 1.4 tsubai sc->sync_tr[cs->chan_num] = 0; 1310 1.1 tsubai else 1311 1.4 tsubai sc->sync_tr[cs->chan_num] = 1312 1.4 tsubai i | scb->msgbuf[4]; 1313 1.1 tsubai #endif /* !NOT_SUPPORT_SYNCTR */ 1314 1.1 tsubai } else { 1315 1.4 tsubai scb->message = MSG_MREJ; 1316 1.4 tsubai SET_CMD(sc, SCMD_AST_ATN); /* assert ATN */ 1317 1.1 tsubai } 1318 1.1 tsubai } 1319 1.1 tsubai } 1320 1.4 tsubai SET_CMD(sc, SCMD_NGT_ACK); 1321 1.1 tsubai } 1322 1.1 tsubai 1323 1.1 tsubai /* 1324 1.1 tsubai * SCSI message send routine 1325 1.1 tsubai */ 1326 1.1 tsubai void 1327 1.15 tsutsui sc_mout(struct sc_softc *sc, struct sc_chan_stat *cs) 1328 1.1 tsubai { 1329 1.15 tsutsui struct sc_scb *scb = cs->scb; 1330 1.15 tsutsui u_char *mp; 1331 1.15 tsutsui int cnt; 1332 1.15 tsutsui int iloop; 1333 1.19 tsutsui uint8_t dummy; 1334 1.19 tsutsui uint8_t tmp; 1335 1.19 tsutsui uint8_t tmp0; 1336 1.1 tsubai 1337 1.4 tsubai flush_fifo(sc); 1338 1.1 tsubai 1339 1.4 tsubai if (sc->mout_flag[cs->chan_num] == 0) { 1340 1.4 tsubai sc->mout_flag[cs->chan_num] = MOUT_IDENTIFY; 1341 1.4 tsubai if (scb->message != 0) { 1342 1.1 tsubai sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG; 1343 1.1 tsubai DMAC_WAIT0; 1344 1.4 tsubai if ((scb->message == MSG_EXTND) 1345 1.4 tsubai && (scb->msgbuf[2] == 0x01)) { 1346 1.1 tsubai cnt = 5; 1347 1.4 tsubai mp = scb->msgbuf; 1348 1.4 tsubai scb->msgbuf[3] = MIN_TP; 1349 1.4 tsubai if (scb->msgbuf[4] > MAX_OFFSET_BYTES) 1350 1.4 tsubai scb->msgbuf[4] = MAX_OFFSET_BYTES; 1351 1.4 tsubai sc->mout_flag[cs->chan_num] = MOUT_SYNC_TR; 1352 1.1 tsubai } else { 1353 1.1 tsubai cnt = 1; 1354 1.4 tsubai mp = &scb->message; 1355 1.1 tsubai } 1356 1.1 tsubai 1357 1.1 tsubai SET_CNT(cnt); 1358 1.4 tsubai SET_CMD(sc, SCMD_TR_INFO|R0_TRBE); 1359 1.4 tsubai sc_datr = scb->identify; 1360 1.1 tsubai DMAC_WAIT0; 1361 1.1 tsubai for (iloop = 1; iloop < cnt; iloop++) { 1362 1.1 tsubai sc_datr = *mp++; 1363 1.1 tsubai DMAC_WAIT; 1364 1.1 tsubai } 1365 1.1 tsubai do { 1366 1.1 tsubai dummy = sc_cmonr; 1367 1.1 tsubai DMAC_WAIT0; 1368 1.1 tsubai if ((dummy & R4_MBSY) == 0) 1369 1.1 tsubai return; 1370 1.1 tsubai dummy = sc_statr; 1371 1.1 tsubai DMAC_WAIT0; 1372 1.1 tsubai } while (dummy & R0_CIP); 1373 1.1 tsubai 1374 1.1 tsubai tmp = 0; 1375 1.1 tsubai GET_INTR(&tmp0, &tmp); /* clear interrupt */ 1376 1.1 tsubai if ((tmp & R3_FNC) == 0) { 1377 1.1 tsubai (void) WAIT_STATR_BITSET(R0_MIRQ); 1378 1.1 tsubai GET_INTR(&tmp0, &tmp); /* clear interrupt */ 1379 1.1 tsubai } 1380 1.1 tsubai 1381 1.1 tsubai do { 1382 1.1 tsubai dummy = sc_cmonr; 1383 1.1 tsubai DMAC_WAIT0; 1384 1.1 tsubai if ((dummy & R4_MBSY) == 0) 1385 1.1 tsubai return; 1386 1.1 tsubai } while ((dummy & R4_MREQ) == 0); 1387 1.4 tsubai SET_CMD(sc, SCMD_NGT_ATN); 1388 1.15 tsutsui (void)WAIT_STATR_BITCLR(R0_CIP); 1389 1.1 tsubai GET_INTR(&tmp0, &tmp); /* clear interrupt */ 1390 1.1 tsubai 1391 1.1 tsubai dummy = sc_cmonr; 1392 1.1 tsubai DMAC_WAIT0; 1393 1.1 tsubai if ((dummy & R4_MREQ) == 0) { 1394 1.1 tsubai printf("sc_mout: !REQ cmonr=%x\n", dummy); 1395 1.4 tsubai print_scsi_stat(sc); 1396 1.1 tsubai scsi_hardreset(); 1397 1.1 tsubai return; 1398 1.1 tsubai } 1399 1.1 tsubai 1400 1.4 tsubai SET_CMD(sc, SCMD_TR_INFO); 1401 1.1 tsubai sc_datr = *mp++; 1402 1.1 tsubai DMAC_WAIT0; 1403 1.1 tsubai } else { 1404 1.1 tsubai dummy = sc_cmonr; 1405 1.1 tsubai DMAC_WAIT0; 1406 1.1 tsubai if (dummy & R4_MATN) { 1407 1.4 tsubai SET_CMD(sc, SCMD_NGT_ATN); 1408 1.1 tsubai (void) WAIT_STATR_BITCLR(R0_CIP); 1409 1.1 tsubai GET_INTR(&tmp0, &tmp); /* clear interrupt */ 1410 1.1 tsubai } 1411 1.1 tsubai 1412 1.1 tsubai iloop = 0; 1413 1.1 tsubai do { 1414 1.1 tsubai dummy = sc_cmonr; 1415 1.1 tsubai DMAC_WAIT0; 1416 1.1 tsubai if (iloop++ > CHECK_LOOP_CNT) 1417 1.1 tsubai break; 1418 1.1 tsubai } while ((dummy & R4_MREQ) == 0); 1419 1.4 tsubai SET_CMD(sc, SCMD_TR_INFO); 1420 1.4 tsubai sc_datr = scb->identify; 1421 1.1 tsubai DMAC_WAIT0; 1422 1.1 tsubai } 1423 1.1 tsubai } else { 1424 1.1 tsubai dummy = sc_cmonr; 1425 1.1 tsubai DMAC_WAIT0; 1426 1.1 tsubai if (dummy & R4_MATN) { 1427 1.4 tsubai SET_CMD(sc, SCMD_NGT_ATN); 1428 1.1 tsubai (void) WAIT_STATR_BITCLR(R0_CIP); 1429 1.1 tsubai GET_INTR(&tmp0, &tmp); /* clear interrupt */ 1430 1.1 tsubai } 1431 1.1 tsubai 1432 1.1 tsubai dummy = sc_cmonr; 1433 1.1 tsubai DMAC_WAIT0; 1434 1.1 tsubai if ((dummy & R4_MREQ) == 0) { 1435 1.1 tsubai printf("sc_mout: !REQ cmonr=%x\n", dummy); 1436 1.4 tsubai print_scsi_stat(sc); 1437 1.1 tsubai scsi_hardreset(); 1438 1.1 tsubai return; 1439 1.1 tsubai } 1440 1.1 tsubai 1441 1.4 tsubai SET_CMD(sc, SCMD_TR_INFO); 1442 1.4 tsubai sc_datr = scb->message; 1443 1.1 tsubai DMAC_WAIT0; 1444 1.1 tsubai } 1445 1.1 tsubai } 1446 1.1 tsubai 1447 1.1 tsubai /* 1448 1.1 tsubai * SCSI status accept routine 1449 1.1 tsubai */ 1450 1.1 tsubai void 1451 1.15 tsutsui sc_sin(struct sc_softc *sc, volatile struct sc_chan_stat *cs) 1452 1.1 tsubai { 1453 1.19 tsutsui uint8_t dummy; 1454 1.15 tsutsui int iloop; 1455 1.1 tsubai 1456 1.4 tsubai flush_fifo(sc); 1457 1.1 tsubai 1458 1.1 tsubai dummy = sc_cmonr; 1459 1.1 tsubai DMAC_WAIT0; 1460 1.1 tsubai if ((dummy & R4_MREQ) == 0) { 1461 1.1 tsubai printf("sc_sin: !REQ cmonr=%x\n", dummy); 1462 1.4 tsubai print_scsi_stat(sc); 1463 1.1 tsubai scsi_hardreset(); 1464 1.1 tsubai return; 1465 1.1 tsubai } 1466 1.1 tsubai 1467 1.1 tsubai sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG; 1468 1.1 tsubai DMAC_WAIT0; 1469 1.1 tsubai 1470 1.4 tsubai SET_CMD(sc, SCMD_TR_INFO); 1471 1.1 tsubai 1472 1.15 tsutsui (void)WAIT_STATR_BITCLR(R0_CIP); 1473 1.1 tsubai 1474 1.4 tsubai sc->int_stat2 &= ~R3_FNC; 1475 1.1 tsubai iloop = 0; 1476 1.1 tsubai do { 1477 1.1 tsubai if (iloop++ > CHECK_LOOP_CNT) 1478 1.1 tsubai break; 1479 1.4 tsubai GET_INTR(&sc->int_stat1, &sc->int_stat2); /* clear interrupt */ 1480 1.4 tsubai } while ((sc->int_stat2 & R3_FNC) == 0); 1481 1.4 tsubai sc->int_stat2 &= ~R3_FNC; 1482 1.1 tsubai 1483 1.4 tsubai cs->scb->tstatus = sc_datr; /* get status byte */ 1484 1.1 tsubai DMAC_WAIT0; 1485 1.1 tsubai } 1486 1.1 tsubai 1487 1.1 tsubai /* 1488 1.1 tsubai * SCSI data in/out routine 1489 1.1 tsubai */ 1490 1.1 tsubai void 1491 1.15 tsutsui sc_dio(struct sc_softc *sc, volatile struct sc_chan_stat *cs) 1492 1.1 tsubai { 1493 1.19 tsutsui struct sc_scb *scb; 1494 1.15 tsutsui int i; 1495 1.15 tsutsui int pages; 1496 1.19 tsutsui uint8_t tag; 1497 1.19 tsutsui uint32_t pfn; 1498 1.19 tsutsui uint8_t phase; 1499 1.4 tsubai struct scsipi_xfer *xs; 1500 1.1 tsubai 1501 1.4 tsubai scb = cs->scb; 1502 1.4 tsubai xs = scb->xs; 1503 1.1 tsubai 1504 1.1 tsubai sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE; 1505 1.1 tsubai DMAC_WAIT0; 1506 1.1 tsubai 1507 1.1 tsubai if (cs->act_trcnt <= 0) { 1508 1.4 tsubai sc_dio_pad(sc, cs); 1509 1.1 tsubai return; 1510 1.1 tsubai } 1511 1.1 tsubai 1512 1.4 tsubai switch (xs->cmd->opcode) { 1513 1.1 tsubai 1514 1.1 tsubai case SCOP_READ: 1515 1.1 tsubai case SCOP_WRITE: 1516 1.1 tsubai case SCOP_EREAD: 1517 1.1 tsubai case SCOP_EWRITE: 1518 1.4 tsubai i = (cs->act_trcnt + DEV_BSIZE -1) / DEV_BSIZE; 1519 1.4 tsubai i *= DEV_BSIZE; 1520 1.1 tsubai break; 1521 1.1 tsubai 1522 1.1 tsubai default: 1523 1.1 tsubai i = cs->act_trcnt; 1524 1.1 tsubai break; 1525 1.1 tsubai } 1526 1.1 tsubai 1527 1.1 tsubai SET_CNT(i); 1528 1.4 tsubai sc->pad_cnt[cs->chan_num] = i - cs->act_trcnt; 1529 1.1 tsubai 1530 1.1 tsubai phase = sc_cmonr & SC_PMASK; 1531 1.1 tsubai DMAC_WAIT0; 1532 1.1 tsubai if (phase == DAT_IN) { 1533 1.1 tsubai if (sc_syncr == OFF) { 1534 1.1 tsubai DMAC_WAIT0; 1535 1.4 tsubai flush_fifo(sc); 1536 1.1 tsubai } 1537 1.1 tsubai } 1538 1.1 tsubai 1539 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 1540 1.4 tsubai SET_CMD(sc, SCMD_TR_INFO|R0_DMA|R0_TRBE); 1541 1.1 tsubai #endif 1542 1.1 tsubai 1543 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 1544 1.1 tsubai dmac_gsel = CH_SCSI; 1545 1.19 tsutsui dmac_ctrcl = (uint8_t)(cs->act_trcnt & 0xff); 1546 1.19 tsutsui dmac_ctrcm = (uint8_t)((cs->act_trcnt >> 8) & 0xff); 1547 1.19 tsutsui dmac_ctrch = (uint8_t)((cs->act_trcnt >> 16) & 0x0f); 1548 1.19 tsutsui dmac_cofsh = (uint8_t)((cs->act_offset >> 8) & 0xf); 1549 1.19 tsutsui dmac_cofsl = (uint8_t)(cs->act_offset & 0xff); 1550 1.1 tsubai #endif 1551 1.1 tsubai tag = 0; 1552 1.1 tsubai 1553 1.4 tsubai if (scb->sc_map && (scb->sc_map->mp_pages > 0)) { 1554 1.1 tsubai /* 1555 1.1 tsubai * Set DMAC map entry from map table 1556 1.1 tsubai */ 1557 1.4 tsubai pages = scb->sc_map->mp_pages; 1558 1.1 tsubai for (i = cs->act_tag; i < pages; i++) { 1559 1.4 tsubai if ((pfn = scb->sc_map->mp_addr[i]) == 0) 1560 1.1 tsubai panic("SCSI:sc_dma() zero entry"); 1561 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 1562 1.1 tsubai dmac_gsel = CH_SCSI; 1563 1.19 tsutsui dmac_ctag = (uint8_t)tag++; 1564 1.19 tsutsui dmac_cmap = (uint16_t)pfn; 1565 1.1 tsubai #endif 1566 1.1 tsubai } 1567 1.1 tsubai #ifdef MAP_OVER_ACCESS 1568 1.9 thorpej # if defined(__mips__) && defined(CPU_SINGLE) 1569 1.1 tsubai dmac_gsel = CH_SCSI; 1570 1.19 tsutsui dmac_ctag = (uint8_t)tag++; 1571 1.19 tsutsui dmac_cmap = (uint16_t)pfn; 1572 1.1 tsubai # endif 1573 1.1 tsubai #endif 1574 1.1 tsubai } else { 1575 1.1 tsubai /* 1576 1.1 tsubai * Set DMAC map entry from logical address 1577 1.1 tsubai */ 1578 1.5 tsubai pfn = kvtophys((vaddr_t)cs->act_point) >> PGSHIFT; 1579 1.1 tsubai pages = (cs->act_trcnt >> PGSHIFT) + 2; 1580 1.1 tsubai for (i = 0; i < pages; i++) { 1581 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 1582 1.1 tsubai dmac_gsel = CH_SCSI; 1583 1.19 tsutsui dmac_ctag = (uint8_t)tag++; 1584 1.19 tsutsui dmac_cmap = (uint8_t)pfn + i; 1585 1.1 tsubai #endif 1586 1.1 tsubai } 1587 1.1 tsubai } 1588 1.1 tsubai 1589 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 1590 1.1 tsubai dmac_gsel = CH_SCSI; 1591 1.1 tsubai dmac_ctag = 0; 1592 1.1 tsubai #endif 1593 1.1 tsubai 1594 1.1 tsubai if (phase == DAT_IN) { 1595 1.4 tsubai sc->dma_stat = SC_DMAC_RD; 1596 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 1597 1.1 tsubai /* 1598 1.1 tsubai * auto pad flag is always on 1599 1.1 tsubai */ 1600 1.1 tsubai dmac_gsel = CH_SCSI; 1601 1.1 tsubai dmac_cctl = DM_MODE|DM_APAD; 1602 1.1 tsubai DMAC_WAIT; 1603 1.1 tsubai dmac_cctl = DM_MODE|DM_APAD|DM_ENABLE; 1604 1.1 tsubai DMAC_WAIT0; 1605 1.1 tsubai #endif 1606 1.1 tsubai } 1607 1.1 tsubai else if (phase == DAT_OUT) { 1608 1.4 tsubai sc->dma_stat = SC_DMAC_WR; 1609 1.9 thorpej #if defined(__mips__) && defined(CPU_SINGLE) 1610 1.1 tsubai dmac_gsel = CH_SCSI; 1611 1.1 tsubai dmac_cctl = DM_APAD; 1612 1.1 tsubai DMAC_WAIT; 1613 1.1 tsubai dmac_cctl = DM_APAD|DM_ENABLE; 1614 1.1 tsubai DMAC_WAIT0; 1615 1.1 tsubai #endif 1616 1.1 tsubai /* DMAC start on mem->I/O */ 1617 1.1 tsubai } 1618 1.1 tsubai } 1619 1.1 tsubai 1620 1.1 tsubai #define MAX_TR_CNT24 ((1 << 24) -1) 1621 1.1 tsubai void 1622 1.15 tsutsui sc_dio_pad(struct sc_softc *sc, volatile struct sc_chan_stat *cs) 1623 1.1 tsubai { 1624 1.19 tsutsui uint8_t dummy; 1625 1.1 tsubai 1626 1.1 tsubai if (cs->act_trcnt >= 0) 1627 1.1 tsubai return; 1628 1.4 tsubai sc->pad_start = 1; 1629 1.1 tsubai 1630 1.1 tsubai SET_CNT(MAX_TR_CNT24); 1631 1.4 tsubai SET_CMD(sc, SCMD_TR_PAD|R0_TRBE); 1632 1.1 tsubai dummy = sc_cmonr & SC_PMASK; 1633 1.1 tsubai DMAC_WAIT0; 1634 1.1 tsubai if (dummy == DAT_IN) 1635 1.1 tsubai dummy = sc_datr; /* get data */ 1636 1.1 tsubai else 1637 1.1 tsubai sc_datr = 0; /* send data */ 1638 1.1 tsubai } 1639 1.1 tsubai 1640 1.1 tsubai void 1641 1.15 tsutsui print_scsi_stat(struct sc_softc *sc) 1642 1.1 tsubai { 1643 1.15 tsutsui 1644 1.4 tsubai printf("ipc=%d wrc=%d wbc=%d\n", sc->ipc, sc->wrc, sc->wbc); 1645 1.1 tsubai } 1646 1.1 tsubai 1647 1.1 tsubai /* 1648 1.24 msaitoh * return 0 if it was done. Or return TRUE if it is busy. 1649 1.1 tsubai */ 1650 1.1 tsubai int 1651 1.15 tsutsui sc_busy(struct sc_softc *sc, int chan) 1652 1.1 tsubai { 1653 1.15 tsutsui 1654 1.15 tsutsui return (int)sc->chan_stat[chan].scb; 1655 1.1 tsubai } 1656 1.1 tsubai 1657 1.1 tsubai 1658 1.1 tsubai /* 1659 1.1 tsubai * append channel into Waiting Bus_free queue 1660 1.1 tsubai */ 1661 1.1 tsubai void 1662 1.15 tsutsui append_wb(struct sc_softc *sc, struct sc_chan_stat *cs) 1663 1.1 tsubai { 1664 1.4 tsubai int s; 1665 1.1 tsubai 1666 1.1 tsubai s = splclock(); /* inhibit process switch */ 1667 1.4 tsubai if (sc->wbq_actf == NULL) 1668 1.4 tsubai sc->wbq_actf = cs; 1669 1.1 tsubai else 1670 1.4 tsubai sc->wbq_actl->wb_next = cs; 1671 1.4 tsubai sc->wbq_actl = cs; 1672 1.4 tsubai cs->scb->istatus = INST_WAIT; 1673 1.4 tsubai sc->wbc++; 1674 1.1 tsubai splx(s); 1675 1.1 tsubai } 1676 1.1 tsubai 1677 1.1 tsubai /* 1678 1.1 tsubai * get channel from Waiting Bus_free queue 1679 1.1 tsubai */ 1680 1.4 tsubai struct sc_chan_stat * 1681 1.15 tsutsui get_wb_chan(struct sc_softc *sc) 1682 1.1 tsubai { 1683 1.4 tsubai struct sc_chan_stat *cs; 1684 1.4 tsubai int s; 1685 1.1 tsubai 1686 1.1 tsubai s = splclock(); /* inhibit process switch */ 1687 1.4 tsubai cs = sc->wbq_actf; 1688 1.4 tsubai if (cs && cs->chan_num == SC_OWNID) /* needed? */ 1689 1.4 tsubai cs = NULL; 1690 1.1 tsubai splx(s); 1691 1.4 tsubai return cs; 1692 1.1 tsubai } 1693 1.1 tsubai 1694 1.1 tsubai /* 1695 1.1 tsubai * release channel from Waiting Bus_free queue 1696 1.1 tsubai */ 1697 1.1 tsubai int 1698 1.15 tsutsui release_wb(struct sc_softc *sc) 1699 1.1 tsubai { 1700 1.4 tsubai struct sc_chan_stat *cs; 1701 1.4 tsubai int error = 0; 1702 1.4 tsubai int s; 1703 1.1 tsubai 1704 1.1 tsubai s = splclock(); /* inhibit process switch */ 1705 1.4 tsubai if (sc->wbq_actf == NULL) { 1706 1.1 tsubai error = -1; 1707 1.1 tsubai } else { 1708 1.4 tsubai cs = sc->wbq_actf; 1709 1.4 tsubai sc->wbq_actf = cs->wb_next; 1710 1.1 tsubai cs->wb_next = NULL; 1711 1.4 tsubai if (sc->wbq_actl == cs) 1712 1.4 tsubai sc->wbq_actl = NULL; 1713 1.4 tsubai cs->scb->istatus &= ~INST_WAIT; 1714 1.4 tsubai sc->wbc--; 1715 1.1 tsubai } 1716 1.1 tsubai splx(s); 1717 1.4 tsubai return error; 1718 1.1 tsubai } 1719 1.1 tsubai 1720 1.1 tsubai void 1721 1.15 tsutsui adjust_transfer(struct sc_softc *sc, struct sc_chan_stat *cs) 1722 1.1 tsubai { 1723 1.4 tsubai struct sc_scb *scb = cs->scb; 1724 1.22 martin u_int remain_cnt = 0; 1725 1.4 tsubai u_int offset, sent_byte; 1726 1.1 tsubai 1727 1.4 tsubai if (sc->pad_start) { 1728 1.4 tsubai sc->pad_start = 0; 1729 1.1 tsubai } else { 1730 1.9 thorpej # if defined(__mips__) && defined(CPU_SINGLE) 1731 1.1 tsubai remain_cnt = GET_CNT(); 1732 1.4 tsubai remain_cnt -= sc->pad_cnt[cs->chan_num]; 1733 1.4 tsubai if (sc->dma_stat == SC_DMAC_WR) { 1734 1.1 tsubai /* 1735 1.1 tsubai * adjust counter in the FIFO 1736 1.1 tsubai */ 1737 1.1 tsubai remain_cnt += sc_ffstr & R5_FIFOREM; 1738 1.1 tsubai } 1739 1.1 tsubai # endif 1740 1.1 tsubai } 1741 1.1 tsubai 1742 1.4 tsubai sent_byte = scb->sc_ctrnscnt - remain_cnt; 1743 1.1 tsubai cs->act_trcnt = remain_cnt; 1744 1.1 tsubai 1745 1.4 tsubai offset = scb->sc_coffset + sent_byte; 1746 1.1 tsubai cs->act_tag += (offset >> PGSHIFT); 1747 1.1 tsubai cs->act_offset = offset & PGOFSET; 1748 1.4 tsubai if ((scb->sc_map == NULL) || (scb->sc_map->mp_pages <= 0)) 1749 1.1 tsubai cs->act_point += sent_byte; 1750 1.1 tsubai } 1751 1.3 tsubai 1752 1.9 thorpej #ifdef __mips__ 1753 1.3 tsubai static void 1754 1.15 tsutsui clean_k2dcache(struct sc_scb *scb) 1755 1.3 tsubai { 1756 1.4 tsubai struct sc_map *sc_map = scb->sc_map; 1757 1.5 tsubai paddr_t pa; 1758 1.3 tsubai int i, pages; 1759 1.3 tsubai 1760 1.5 tsubai pa = kvtophys((vaddr_t)scb->msgbuf); 1761 1.8 thorpej mips_dcache_wbinv_range_index(MIPS_PHYS_TO_KSEG0(pa), 1762 1.8 thorpej sizeof(scb->msgbuf)); 1763 1.4 tsubai 1764 1.4 tsubai if (MACH_IS_USPACE(scb->sc_cpoint)) 1765 1.4 tsubai panic("clean_k2dcache: user address is not supported"); 1766 1.4 tsubai 1767 1.4 tsubai if (MACH_IS_CACHED(scb->sc_cpoint)) { 1768 1.8 thorpej mips_dcache_wbinv_range_index((vaddr_t)scb->sc_cpoint, 1769 1.8 thorpej scb->sc_ctrnscnt); 1770 1.3 tsubai return; 1771 1.4 tsubai } 1772 1.3 tsubai 1773 1.4 tsubai if (sc_map) { 1774 1.4 tsubai pages = sc_map->mp_pages; 1775 1.4 tsubai for (i = 0; i < pages; i++) { 1776 1.4 tsubai pa = sc_map->mp_addr[i] << PGSHIFT; 1777 1.8 thorpej mips_dcache_wbinv_range_index(MIPS_PHYS_TO_KSEG0(pa), 1778 1.10 thorpej PAGE_SIZE); 1779 1.4 tsubai } 1780 1.3 tsubai } 1781 1.3 tsubai } 1782 1.3 tsubai #endif 1783