1 /* $NetBSD: asc.c,v 1.6 2001/11/14 18:15:15 thorpej Exp $ */ 2 /* $OpenBSD: asc.c,v 1.9 1998/03/16 09:38:39 pefo Exp $ */ 3 /* NetBSD: asc.c,v 1.10 1994/12/05 19:11:12 dean Exp */ 4 5 /*- 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Ralph Campbell and Rick Macklem. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)asc.c 8.3 (Berkeley) 7/3/94 41 */ 42 43 /* 44 * Mach Operating System 45 * Copyright (c) 1991,1990,1989 Carnegie Mellon University 46 * All Rights Reserved. 47 * 48 * Permission to use, copy, modify and distribute this software and its 49 * documentation is hereby granted, provided that both the copyright 50 * notice and this permission notice appear in all copies of the 51 * software, derivative works or modified versions, and any portions 52 * thereof, and that both notices appear in supporting documentation. 53 * 54 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 55 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 56 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 57 * 58 * Carnegie Mellon requests users of this software to return to 59 * 60 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 61 * School of Computer Science 62 * Carnegie Mellon University 63 * Pittsburgh PA 15213-3890 64 * 65 * any improvements or extensions that they make and grant Carnegie the 66 * rights to redistribute these changes. 67 */ 68 69 /* 70 * HISTORY 71 * Log: scsi_53C94_hdw.c,v 72 * Revision 2.5 91/02/05 17:45:07 mrt 73 * Added author notices 74 * [91/02/04 11:18:43 mrt] 75 * 76 * Changed to use new Mach copyright 77 * [91/02/02 12:17:20 mrt] 78 * 79 * Revision 2.4 91/01/08 15:48:24 rpd 80 * Added continuation argument to thread_block. 81 * [90/12/27 rpd] 82 * 83 * Revision 2.3 90/12/05 23:34:48 af 84 * Recovered from pmax merge.. and from the destruction of a disk. 85 * [90/12/03 23:40:40 af] 86 * 87 * Revision 2.1.1.1 90/11/01 03:39:09 af 88 * Created, from the DEC specs: 89 * "PMAZ-AA TURBOchannel SCSI Module Functional Specification" 90 * Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990. 91 * And from the NCR data sheets 92 * "NCR 53C94, 53C95, 53C96 Advances SCSI Controller" 93 * [90/09/03 af] 94 */ 95 96 /* 97 * File: scsi_53C94_hdw.h 98 * Author: Alessandro Forin, Carnegie Mellon University 99 * Date: 9/90 100 * 101 * Bottom layer of the SCSI driver: chip-dependent functions 102 * 103 * This file contains the code that is specific to the NCR 53C94 104 * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start 105 * operation, and interrupt routine. 106 */ 107 108 /* 109 * This layer works based on small simple 'scripts' that are installed 110 * at the start of the command and drive the chip to completion. 111 * The idea comes from the specs of the NCR 53C700 'script' processor. 112 * 113 * There are various reasons for this, mainly 114 * - Performance: identify the common (successful) path, and follow it; 115 * at interrupt time no code is needed to find the current status 116 * - Code size: it should be easy to compact common operations 117 * - Adaptability: the code skeleton should adapt to different chips without 118 * terrible complications. 119 * - Error handling: and it is easy to modify the actions performed 120 * by the scripts to cope with strange but well identified sequences 121 * 122 */ 123 124 #include <sys/param.h> 125 #include <sys/systm.h> 126 #include <sys/dkstat.h> 127 #include <sys/buf.h> 128 #include <sys/proc.h> 129 #include <sys/conf.h> 130 #include <sys/errno.h> 131 #include <sys/device.h> 132 #include <uvm/uvm_extern.h> 133 134 #include <dev/scsipi/scsi_all.h> 135 #include <dev/scsipi/scsipi_all.h> 136 #include <dev/scsipi/scsiconf.h> 137 138 #include <mips/cache.h> 139 140 #include <machine/cpu.h> 141 #include <machine/autoconf.h> 142 #include <machine/bus.h> 143 144 #include <arc/jazz/jazziovar.h> 145 #include <arc/jazz/jazzdmatlbreg.h> 146 #include <arc/jazz/dma.h> 147 #include <arc/jazz/scsi.h> 148 #include <arc/jazz/ascreg.h> 149 #include <arc/jazz/ascvar.h> 150 151 #include <arc/jazz/pica.h> 152 153 154 #define readback(a) { register int foo; foo = (a); } 155 156 /* 157 * In 4ns ticks. 158 */ 159 int asc_to_scsi_period[] = { 160 32, 161 33, 162 34, 163 35, 164 5, 165 5, 166 6, 167 7, 168 8, 169 9, 170 10, 171 11, 172 12, 173 13, 174 14, 175 15, 176 16, 177 17, 178 18, 179 19, 180 20, 181 21, 182 22, 183 23, 184 24, 185 25, 186 26, 187 27, 188 28, 189 29, 190 30, 191 31, 192 }; 193 194 /* 195 * Internal forward declarations. 196 */ 197 struct asc_softc; 198 static void asc_reset __P((struct asc_softc *, asc_regmap_t *)); 199 static void asc_startcmd __P((struct asc_softc *, int)); 200 201 #ifdef DEBUG 202 int asc_debug = 1; 203 int asc_debug_cmd; 204 int asc_debug_bn; 205 int asc_debug_sz; 206 #define NLOG 16 207 struct asc_log { 208 u_int status; 209 u_char state; 210 u_char msg; 211 int target; 212 int resid; 213 } asc_log[NLOG], *asc_logp = asc_log; 214 #define PACK(unit, status, ss, ir) \ 215 ((unit << 24) | (status << 16) | (ss << 8) | ir) 216 #endif 217 218 /* 219 * Scripts are entries in a state machine table. 220 * A script has four parts: a pre-condition, an action, a command to the chip, 221 * and an index into asc_scripts for the next state. The first triggers error 222 * handling if not satisfied and in our case it is formed by the 223 * values of the interrupt register and status register, this 224 * basically captures the phase of the bus and the TC and BS 225 * bits. The action part is just a function pointer, and the 226 * command is what the 53C94 should be told to do at the end 227 * of the action processing. This command is only issued and the 228 * script proceeds if the action routine returns TRUE. 229 * See asc_intr() for how and where this is all done. 230 */ 231 typedef struct script { 232 int condition; /* expected state at interrupt time */ 233 int (*action)(struct asc_softc *, int, int, int); 234 /* extra operations */ 235 int command; /* command to the chip */ 236 struct script *next; /* index into asc_scripts for next state */ 237 } script_t; 238 239 /* Matching on the condition value */ 240 #define SCRIPT_MATCH(ir, csr) ((ir) | (((csr) & 0x67) << 8)) 241 242 243 /* forward decls of script actions */ 244 /* when nothing needed */ 245 static int script_nop __P((struct asc_softc *, int, int, int)); 246 /* all come to an end */ 247 static int asc_end __P((struct asc_softc *, int, int, int)); 248 /* get status from target */ 249 static int asc_get_status __P((struct asc_softc *, int, int, int)); 250 /* start reading data from target */ 251 static int asc_dma_in __P((struct asc_softc *, int, int, int)); 252 /* cleanup after all data is read */ 253 static int asc_last_dma_in __P((struct asc_softc *, int, int, int)); 254 /* resume data in after a message */ 255 static int asc_resume_in __P((struct asc_softc *, int, int, int)); 256 /* resume DMA after a disconnect */ 257 static int asc_resume_dma_in __P((struct asc_softc *, int, int, int)); 258 /* send data to target via dma */ 259 static int asc_dma_out __P((struct asc_softc *, int, int, int)); 260 /* cleanup after all data is written */ 261 static int asc_last_dma_out __P((struct asc_softc *, int, int, int)); 262 /* resume data out after a message */ 263 static int asc_resume_out __P((struct asc_softc *, int, int, int)); 264 /* resume DMA after a disconnect */ 265 static int asc_resume_dma_out __P((struct asc_softc *, int, int, int)); 266 /* negotiate sync xfer */ 267 static int asc_sendsync __P((struct asc_softc *, int, int, int)); 268 /* negotiate sync xfer */ 269 static int asc_replysync __P((struct asc_softc *, int, int, int)); 270 /* process a message byte */ 271 static int asc_msg_in __P((struct asc_softc *, int, int, int)); 272 /* process an expected disconnect */ 273 static int asc_disconnect __P((struct asc_softc *, int, int, int)); 274 275 /* Define the index into asc_scripts for various state transitions */ 276 #define SCRIPT_DATA_IN 0 277 #define SCRIPT_CONTINUE_IN 2 278 #define SCRIPT_DATA_OUT 3 279 #define SCRIPT_CONTINUE_OUT 5 280 #define SCRIPT_SIMPLE 6 281 #define SCRIPT_GET_STATUS 7 282 #define SCRIPT_DONE 8 283 #define SCRIPT_MSG_IN 9 284 #define SCRIPT_REPLY_SYNC 11 285 #define SCRIPT_TRY_SYNC 12 286 #define SCRIPT_DISCONNECT 15 287 #define SCRIPT_RESEL 16 288 #define SCRIPT_RESUME_IN 17 289 #define SCRIPT_RESUME_DMA_IN 18 290 #define SCRIPT_RESUME_OUT 19 291 #define SCRIPT_RESUME_DMA_OUT 20 292 #define SCRIPT_RESUME_NO_DATA 21 293 294 /* 295 * Scripts 296 */ 297 script_t asc_scripts[] = { 298 /* start data in */ 299 {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAI), /* 0 */ 300 asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 301 &asc_scripts[SCRIPT_DATA_IN + 1]}, 302 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 1 */ 303 asc_last_dma_in, ASC_CMD_I_COMPLETE, 304 &asc_scripts[SCRIPT_GET_STATUS]}, 305 306 /* continue data in after a chunk is finished */ 307 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 2 */ 308 asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 309 &asc_scripts[SCRIPT_DATA_IN + 1]}, 310 311 /* start data out */ 312 {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAO), /* 3 */ 313 asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 314 &asc_scripts[SCRIPT_DATA_OUT + 1]}, 315 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 4 */ 316 asc_last_dma_out, ASC_CMD_I_COMPLETE, 317 &asc_scripts[SCRIPT_GET_STATUS]}, 318 319 /* continue data out after a chunk is finished */ 320 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 5 */ 321 asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 322 &asc_scripts[SCRIPT_DATA_OUT + 1]}, 323 324 /* simple command with no data transfer */ 325 {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_STATUS), /* 6 */ 326 script_nop, ASC_CMD_I_COMPLETE, 327 &asc_scripts[SCRIPT_GET_STATUS]}, 328 329 /* get status and finish command */ 330 {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 7 */ 331 asc_get_status, ASC_CMD_MSG_ACPT, 332 &asc_scripts[SCRIPT_DONE]}, 333 {SCRIPT_MATCH(ASC_INT_DISC, 0), /* 8 */ 334 asc_end, ASC_CMD_NOP, 335 &asc_scripts[SCRIPT_DONE]}, 336 337 /* message in */ 338 {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 9 */ 339 asc_msg_in, ASC_CMD_MSG_ACPT, 340 &asc_scripts[SCRIPT_MSG_IN + 1]}, 341 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 10 */ 342 script_nop, ASC_CMD_XFER_INFO, 343 &asc_scripts[SCRIPT_MSG_IN]}, 344 345 /* send synchonous negotiation reply */ 346 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 11 */ 347 asc_replysync, ASC_CMD_XFER_INFO, 348 &asc_scripts[SCRIPT_REPLY_SYNC]}, 349 350 /* try to negotiate synchonous transfer parameters */ 351 {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 12 */ 352 asc_sendsync, ASC_CMD_XFER_INFO, 353 &asc_scripts[SCRIPT_TRY_SYNC + 1]}, 354 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 13 */ 355 script_nop, ASC_CMD_XFER_INFO, 356 &asc_scripts[SCRIPT_MSG_IN]}, 357 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_COMMAND), /* 14 */ 358 script_nop, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 359 &asc_scripts[SCRIPT_RESUME_NO_DATA]}, 360 361 /* handle a disconnect */ 362 {SCRIPT_MATCH(ASC_INT_DISC, ASC_PHASE_DATAO), /* 15 */ 363 asc_disconnect, ASC_CMD_ENABLE_SEL, 364 &asc_scripts[SCRIPT_RESEL]}, 365 366 /* reselect sequence: this is just a placeholder so match fails */ 367 {SCRIPT_MATCH(0, ASC_PHASE_MSG_IN), /* 16 */ 368 script_nop, ASC_CMD_MSG_ACPT, 369 &asc_scripts[SCRIPT_RESEL]}, 370 371 /* resume data in after a message */ 372 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 17 */ 373 asc_resume_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 374 &asc_scripts[SCRIPT_DATA_IN + 1]}, 375 376 /* resume partial DMA data in after a message */ 377 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 18 */ 378 asc_resume_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 379 &asc_scripts[SCRIPT_DATA_IN + 1]}, 380 381 /* resume data out after a message */ 382 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 19 */ 383 asc_resume_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 384 &asc_scripts[SCRIPT_DATA_OUT + 1]}, 385 386 /* resume partial DMA data out after a message */ 387 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 20 */ 388 asc_resume_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 389 &asc_scripts[SCRIPT_DATA_OUT + 1]}, 390 391 /* resume after a message when there is no more data */ 392 {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 21 */ 393 script_nop, ASC_CMD_I_COMPLETE, 394 &asc_scripts[SCRIPT_GET_STATUS]}, 395 }; 396 397 /* 398 * State kept for each active SCSI device. 399 */ 400 typedef struct scsi_state { 401 script_t *script; /* saved script while processing error */ 402 struct scsi_generic cmd;/* storage for scsi command */ 403 int statusByte; /* status byte returned during STATUS_PHASE */ 404 u_int dmaBufSize; /* DMA buffer size */ 405 int dmalen; /* amount to transfer in this chunk */ 406 int dmaresid; /* amount not transfered if chunk suspended */ 407 int cmdlen; /* length of command in cmd */ 408 int buflen; /* total remaining amount of data to transfer */ 409 vaddr_t buf; /* current pointer within scsicmd->buf */ 410 int flags; /* see below */ 411 int msglen; /* number of message bytes to read */ 412 int msgcnt; /* number of message bytes received */ 413 u_char sync_period; /* DMA synchronous period */ 414 u_char sync_offset; /* DMA synchronous xfer offset or 0 if async */ 415 u_char msg_out; /* next MSG_OUT byte to send */ 416 u_char msg_in[16]; /* buffer for multibyte messages */ 417 } State; 418 419 /* state flags */ 420 #define DISCONN 0x001 /* true if currently disconnected from bus */ 421 #define DMA_IN_PROGRESS 0x002 /* true if data DMA started */ 422 #define DMA_IN 0x004 /* true if reading from SCSI device */ 423 #define DMA_OUT 0x010 /* true if writing to SCSI device */ 424 #define DID_SYNC 0x020 /* true if synchronous offset was negotiated */ 425 #define TRY_SYNC 0x040 /* true if try neg. synchronous offset */ 426 #define PARITY_ERR 0x080 /* true if parity error seen */ 427 428 /* 429 * State kept for each active SCSI host interface (53C94). 430 */ 431 struct asc_softc { 432 struct device sc_dev; /* use as a device */ 433 asc_regmap_t *regs; /* chip address */ 434 dma_softc_t __dma; /* stupid macro..... */ 435 dma_softc_t *dma; /* dma control structure */ 436 int sc_id; /* SCSI ID of this interface */ 437 int myidmask; /* ~(1 << myid) */ 438 int state; /* current SCSI connection state */ 439 int target; /* target SCSI ID if busy */ 440 script_t *script; /* next expected interrupt & action */ 441 struct scsipi_xfer *cmdq[ASC_NCMD];/* Pointer to queued commands */ 442 struct scsipi_xfer *cmd[ASC_NCMD];/* Pointer to current active command */ 443 State st[ASC_NCMD]; /* state info for each active command */ 444 int min_period; /* Min transfer period clk/byte */ 445 int max_period; /* Max transfer period clk/byte */ 446 int ccf; /* CCF, whatever that really is? */ 447 int timeout_250; /* 250ms timeout */ 448 int tb_ticks; /* 4ns. ticks/tb channel ticks */ 449 int is24bit; /* if 53CF94/96-2, 24bit address */ 450 struct scsipi_channel sc_channel; 451 struct scsipi_adapter sc_adapter; 452 }; 453 454 #define ASC_STATE_IDLE 0 /* idle state */ 455 #define ASC_STATE_BUSY 1 /* selecting or currently connected */ 456 #define ASC_STATE_TARGET 2 /* currently selected as target */ 457 #define ASC_STATE_RESEL 3 /* currently waiting for reselect */ 458 459 typedef struct asc_softc *asc_softc_t; 460 461 struct asc_timing { 462 int min_period; /* Min transfer period clk/byte */ 463 int max_period; /* Max transfer period clk/byte */ 464 int ccf; /* CCF, whatever that really is? */ 465 int timeout_250; /* 250ms timeout */ 466 int tb_ticks; /* 4ns. ticks/tb channel ticks */ 467 } asc_timing_40mhz = { 468 ASC_MIN_PERIOD40, 469 ASC_MAX_PERIOD40, 470 ASC_CCF(40), 471 ASC_TIMEOUT_250(40, 8 /* exception for ASC_CCF(40) (== 0) */), 472 6, /* 6.25 */ 473 }, asc_timing_25mhz = { 474 ASC_MIN_PERIOD25, 475 ASC_MAX_PERIOD25, 476 ASC_CCF(25), 477 ASC_TIMEOUT_250(25, ASC_CCF(25)), 478 10, 479 }, asc_timing_12mhz = { 480 ASC_MIN_PERIOD12, 481 ASC_MAX_PERIOD12, 482 ASC_CCF(13), 483 ASC_TIMEOUT_250(13, ASC_CCF(13)), 484 20, 485 }; 486 487 struct asc_config *asc_conf = NULL; 488 489 /* 490 * Autoconfiguration data for config. 491 */ 492 int ascmatch __P((struct device *, struct cfdata *, void *)); 493 void ascattach __P((struct device *, struct device *, void *)); 494 495 int asc_doprobe __P((void *, int, int, struct device *)); 496 497 struct cfattach asc_ca = { 498 sizeof(struct asc_softc), ascmatch, ascattach 499 }; 500 501 /* 502 * Glue to the machine dependent scsi 503 */ 504 void asc_scsipi_request __P((struct scsipi_channel *, 505 scsipi_adapter_req_t, void *)); 506 507 static int asc_intr __P((void *)); 508 static void asc_poll __P((struct asc_softc *, int)); 509 #ifdef DEBUG 510 static void asc_DumpLog __P((char *)); 511 #endif 512 513 /* 514 * Match driver based on name 515 */ 516 int 517 ascmatch(parent, match, aux) 518 struct device *parent; 519 struct cfdata *match; 520 void *aux; 521 { 522 struct jazzio_attach_args *ja = aux; 523 524 if(strcmp(ja->ja_name, "asc") != 0) 525 return (0); 526 return (1); 527 } 528 529 void 530 ascattach(parent, self, aux) 531 struct device *parent; 532 struct device *self; 533 void *aux; 534 { 535 struct jazzio_attach_args *ja = aux; 536 asc_softc_t asc = (void *)self; 537 asc_regmap_t *regs; 538 int id, s, i; 539 int bufsiz; 540 541 if (asc_conf == NULL) 542 panic("asc_conf isn't initialized"); 543 544 /* 545 * Initialize hw descriptor, cache some pointers 546 */ 547 asc->regs = (asc_regmap_t *)ja->ja_addr; /* XXX */ 548 549 /* 550 * Set up machine dependencies. 551 * 1) how to do dma 552 * 2) timing based on chip clock frequency 553 */ 554 #if 1 /*XXX check if code handles 0 as 64k */ 555 bufsiz = 63 * 1024; 556 #else 557 bufsiz = 64 * 1024; 558 #endif 559 asc->dma = &asc->__dma; 560 asc_dma_init(asc->dma); 561 562 /* 563 * Now for timing. 564 */ 565 asc->min_period = asc_conf->ac_timing->min_period; 566 asc->max_period = asc_conf->ac_timing->max_period; 567 asc->ccf = asc_conf->ac_timing->ccf; 568 asc->timeout_250 = asc_conf->ac_timing->timeout_250; 569 asc->tb_ticks = asc_conf->ac_timing->tb_ticks; 570 571 asc->state = ASC_STATE_IDLE; 572 asc->target = -1; 573 574 regs = asc->regs; 575 576 /* 577 * Reset chip, fully. Note that interrupts are already enabled. 578 */ 579 s = splbio(); 580 581 /* preserve our ID for now */ 582 asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID; 583 asc->myidmask = ~(1 << asc->sc_id); 584 585 /* identify 53CF9x-2 or not */ 586 regs->asc_cmd = ASC_CMD_RESET; 587 wbflush(); DELAY(25); 588 regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP; 589 wbflush(); DELAY(25); 590 regs->asc_cnfg2 = ASC_CNFG2_FE; 591 wbflush(); DELAY(25); 592 regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP; 593 wbflush(); DELAY(25); 594 asc->is24bit = regs->asc_id == ASC_ID_53CF94; 595 596 asc_reset(asc, regs); 597 598 /* 599 * Our SCSI id on the bus. 600 * The user can set this via the prom on 3maxen/picaen. 601 * If this changes it is easy to fix: make a default that 602 * can be changed as boot arg. 603 */ 604 #ifdef unneeded 605 regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) | 606 (scsi_initiator_id[unit] & 0x7); 607 asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID; 608 #endif 609 id = asc->sc_id; 610 splx(s); 611 612 /* 613 * Give each target its DMA buffer region. 614 * The buffer address is the same for all targets, 615 * the allocated dma viritual scatter/gather space. 616 */ 617 for (i = 0; i < ASC_NCMD; i++) { 618 asc->st[i].dmaBufSize = bufsiz; 619 } 620 621 /* 622 * Set up interrupt handler. 623 */ 624 jazzio_intr_establish(ja->ja_intr, asc_intr, (void *)asc); 625 626 printf(": %s, target %d\n", asc->is24bit ? "NCR53CF9X-2" : "NCR53C94", 627 id); 628 629 asc->sc_adapter.adapt_dev = &asc->sc_dev; 630 asc->sc_adapter.adapt_nchannels = 1; 631 asc->sc_adapter.adapt_openings = 7; 632 asc->sc_adapter.adapt_max_periph = 1; 633 asc->sc_adapter.adapt_ioctl = NULL; 634 asc->sc_adapter.adapt_minphys = minphys; 635 asc->sc_adapter.adapt_request = asc_scsipi_request; 636 637 memset(&asc->sc_channel, 0, sizeof(asc->sc_channel)); 638 asc->sc_channel.chan_adapter = &asc->sc_adapter; 639 asc->sc_channel.chan_bustype = &scsi_bustype; 640 asc->sc_channel.chan_channel = 0; 641 asc->sc_channel.chan_ntargets = 8; 642 asc->sc_channel.chan_nluns = 8; 643 asc->sc_channel.chan_id = asc->sc_id; 644 645 /* 646 * Now try to attach all the sub devices. 647 */ 648 config_found(self, &asc->sc_channel, scsiprint); 649 } 650 651 /* 652 * Start activity on a SCSI device. 653 * We maintain information on each device separately since devices can 654 * connect/disconnect during an operation. 655 */ 656 void 657 asc_scsipi_request(chan, req, arg) 658 struct scsipi_channel *chan; 659 scsipi_adapter_req_t req; 660 void *arg; 661 { 662 struct scsipi_xfer *xs; 663 struct scsipi_periph *periph; 664 struct asc_softc *asc = (void *)chan->chan_adapter->adapt_dev; 665 int dontqueue, s; 666 667 switch (req) { 668 case ADAPTER_REQ_RUN_XFER: 669 xs = arg; 670 periph = xs->xs_periph; 671 672 dontqueue = xs->xs_control & XS_CTL_POLL; 673 674 /* 675 * Flush caches for any data buffer 676 */ 677 if(xs->datalen != 0) { 678 mips_dcache_wbinv_range((vaddr_t)xs->data, xs->datalen); 679 } 680 /* 681 * The hack on the next few lines are to avoid buffers 682 * mapped to UADDR. Realloc to the kva uarea address. 683 */ 684 if((u_int)(xs->data) >= UADDR) { 685 xs->data = ((u_int)(xs->data) & ~UADDR) + (u_char *)(curproc->p_addr); 686 } 687 688 s = splbio(); 689 asc->cmd[periph->periph_target] = xs; 690 691 /* 692 * Going to launch. 693 * Make a local copy of the command and some pointers. 694 */ 695 asc_startcmd(asc, periph->periph_target); 696 697 /* 698 * If in startup, interrupts not usable yet. 699 */ 700 if(dontqueue) { 701 asc_poll(asc,periph->periph_target); 702 } 703 splx(s); 704 return; 705 case ADAPTER_REQ_GROW_RESOURCES: 706 /* XXX Not supported. */ 707 return; 708 case ADAPTER_REQ_SET_XFER_MODE: 709 /* XXX Not supported. */ 710 return; 711 } 712 } 713 714 void 715 asc_poll(asc, target) 716 struct asc_softc *asc; 717 int target; 718 { 719 struct scsipi_xfer *scsicmd = asc->cmd[target]; 720 int count = scsicmd->timeout * 10; 721 722 while(count) { 723 if(asc->regs->asc_status &ASC_CSR_INT) { 724 asc_intr(asc); 725 } 726 if(scsicmd->xs_status & XS_STS_DONE) 727 break; 728 DELAY(5); 729 count--; 730 } 731 if(count == 0) { 732 scsicmd->error = XS_TIMEOUT; 733 asc_end(asc, 0, 0, 0); 734 } 735 } 736 737 static void 738 asc_reset(asc, regs) 739 asc_softc_t asc; 740 asc_regmap_t *regs; 741 { 742 743 /* 744 * Reset chip and wait till done 745 */ 746 regs->asc_cmd = ASC_CMD_RESET; 747 wbflush(); DELAY(25); 748 749 /* spec says this is needed after reset */ 750 regs->asc_cmd = ASC_CMD_NOP; 751 wbflush(); DELAY(25); 752 753 /* 754 * Set up various chip parameters 755 */ 756 regs->asc_ccf = asc->ccf; 757 wbflush(); DELAY(25); 758 regs->asc_sel_timo = asc->timeout_250; 759 /* restore our ID */ 760 regs->asc_cnfg1 = asc->sc_id | ASC_CNFG1_P_CHECK; 761 /* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */ 762 regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL; 763 regs->asc_cnfg3 = asc_conf->ac_cnfg3; 764 /* zero anything else */ 765 ASC_TC_PUT(regs, 0, asc->is24bit); 766 regs->asc_syn_p = asc->min_period; 767 regs->asc_syn_o = 0; /* async for now */ 768 wbflush(); 769 } 770 771 /* 772 * Start a SCSI command on a target. 773 */ 774 static void 775 asc_startcmd(asc, target) 776 asc_softc_t asc; 777 int target; 778 { 779 asc_regmap_t *regs; 780 State *state; 781 struct scsipi_xfer *scsicmd; 782 int i, len; 783 784 /* 785 * See if another target is currently selected on this SCSI bus. 786 */ 787 if (asc->target >= 0) 788 return; 789 790 regs = asc->regs; 791 792 /* 793 * If a reselection is in progress, it is Ok to ignore it since 794 * the ASC will automatically cancel the command and flush 795 * the FIFO if the ASC is reselected before the command starts. 796 * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if 797 * a reselect occurs before starting the command. 798 */ 799 800 asc->state = ASC_STATE_BUSY; 801 asc->target = target; 802 803 /* cache some pointers */ 804 scsicmd = asc->cmd[target]; 805 state = &asc->st[target]; 806 807 /* 808 * Init the chip and target state. 809 */ 810 state->flags = state->flags & DID_SYNC; 811 state->script = (script_t *)0; 812 state->msg_out = SCSI_NO_OP; 813 814 /* 815 * Set up for DMA of command output. Also need to flush cache. 816 */ 817 bcopy(scsicmd->cmd, &state->cmd, scsicmd->cmdlen); 818 state->cmdlen = scsicmd->cmdlen; 819 state->buf = (vaddr_t)scsicmd->data; 820 state->buflen = scsicmd->datalen; 821 len = state->cmdlen; 822 state->dmalen = len; 823 824 #ifdef DEBUG 825 if (asc_debug > 1) { 826 printf("asc_startcmd: %s target %d cmd %x len %d\n", 827 asc->sc_dev.dv_xname, target, 828 state->cmd.opcode, state->buflen); 829 } 830 #endif 831 832 /* check for simple SCSI command with no data transfer */ 833 if (scsicmd->xs_control & XS_CTL_DATA_OUT) { 834 asc->script = &asc_scripts[SCRIPT_DATA_OUT]; 835 state->flags |= DMA_OUT; 836 } 837 else if (scsicmd->xs_control & XS_CTL_DATA_IN) { 838 asc->script = &asc_scripts[SCRIPT_DATA_IN]; 839 state->flags |= DMA_IN; 840 } 841 else if (state->buflen == 0) { 842 /* check for sync negotiation */ 843 if ((scsicmd->xs_status & /* SCSICMD_USE_SYNC */ 0) && 844 !(state->flags & DID_SYNC)) { 845 asc->script = &asc_scripts[SCRIPT_TRY_SYNC]; 846 state->flags |= TRY_SYNC; 847 } else 848 asc->script = &asc_scripts[SCRIPT_SIMPLE]; 849 state->buf = (vaddr_t)0; 850 } 851 852 #ifdef DEBUG 853 asc_debug_cmd = state->cmd.opcode; 854 if (state->cmd.opcode == SCSI_READ_EXT) { 855 asc_debug_bn = (state->cmd.bytes[1] << 24) | 856 (state->cmd.bytes[2] << 16) | 857 (state->cmd.bytes[3] << 8) | 858 state->cmd.bytes[4]; 859 asc_debug_sz = (state->cmd.bytes[6] << 8) | state->cmd.bytes[7]; 860 } 861 asc_logp->status = PACK(asc->sc_dev.dv_unit, 0, 0, asc_debug_cmd); 862 asc_logp->target = asc->target; 863 asc_logp->state = asc->script - asc_scripts; 864 asc_logp->msg = SCSI_DIS_REC_IDENTIFY; 865 asc_logp->resid = scsicmd->datalen; 866 if (++asc_logp >= &asc_log[NLOG]) 867 asc_logp = asc_log; 868 #endif 869 870 /* preload the FIFO with the message and command to be sent */ 871 regs->asc_fifo = SCSI_DIS_REC_IDENTIFY | 872 (scsicmd->xs_periph->periph_lun & 0x07); 873 874 for( i = 0; i < len; i++ ) { 875 regs->asc_fifo = ((caddr_t)&state->cmd)[i]; 876 } 877 ASC_TC_PUT(regs, 0, asc->is24bit); 878 readback(regs->asc_cmd); 879 regs->asc_cmd = ASC_CMD_DMA; 880 readback(regs->asc_cmd); 881 882 regs->asc_dbus_id = target; 883 readback(regs->asc_dbus_id); 884 regs->asc_syn_p = state->sync_period; 885 readback(regs->asc_syn_p); 886 regs->asc_syn_o = state->sync_offset; 887 readback(regs->asc_syn_o); 888 889 /*XXX PEFO */ 890 /* we are not using sync transfer now, need to check this if we will */ 891 892 if (state->flags & TRY_SYNC) 893 regs->asc_cmd = ASC_CMD_SEL_ATN_STOP; 894 else 895 regs->asc_cmd = ASC_CMD_SEL_ATN; 896 readback(regs->asc_cmd); 897 } 898 899 /* 900 * Interrupt routine 901 * Take interrupts from the chip 902 * 903 * Implementation: 904 * Move along the current command's script if 905 * all is well, invoke error handler if not. 906 */ 907 int 908 asc_intr(sc) 909 void *sc; 910 { 911 asc_softc_t asc = sc; 912 asc_regmap_t *regs = asc->regs; 913 State *state; 914 script_t *scpt; 915 int ss, ir, status; 916 917 /* collect ephemeral information */ 918 status = regs->asc_status; 919 ss = regs->asc_ss; 920 921 if ((status & ASC_CSR_INT) == 0) /* Make shure it's a real interrupt */ 922 return(0); 923 924 ir = regs->asc_intr; /* this resets the previous two */ 925 scpt = asc->script; 926 927 #ifdef DEBUG 928 asc_logp->status = PACK(asc->sc_dev.dv_unit, status, ss, ir); 929 asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1; 930 asc_logp->state = scpt - asc_scripts; 931 asc_logp->msg = -1; 932 asc_logp->resid = 0; 933 if (++asc_logp >= &asc_log[NLOG]) 934 asc_logp = asc_log; 935 if (asc_debug > 2) 936 printf("asc_intr: status %x ss %x ir %x cond %d:%x\n", 937 status, ss, ir, scpt - asc_scripts, scpt->condition); 938 #endif 939 940 /* check the expected state */ 941 if (SCRIPT_MATCH(ir, status) == scpt->condition) { 942 /* 943 * Perform the appropriate operation, then proceed. 944 */ 945 if ((*scpt->action)(asc, status, ss, ir)) { 946 regs->asc_cmd = scpt->command; 947 readback(regs->asc_cmd); 948 asc->script = scpt->next; 949 } 950 goto done; 951 } 952 953 /* 954 * Check for parity error. 955 * Hardware will automatically set ATN 956 * to request the device for a MSG_OUT phase. 957 */ 958 if (status & ASC_CSR_PE) { 959 printf("%s: SCSI device %d: incomming parity error seen\n", 960 asc->sc_dev.dv_xname, asc->target); 961 asc->st[asc->target].flags |= PARITY_ERR; 962 } 963 964 /* 965 * Check for gross error. 966 * Probably a bug in a device driver. 967 */ 968 if (status & ASC_CSR_GE) { 969 printf("%s: SCSI device %d: gross error\n", 970 asc->sc_dev.dv_xname, asc->target); 971 goto abort; 972 } 973 974 /* check for message in or out */ 975 if ((ir & ~ASC_INT_FC) == ASC_INT_BS) { 976 register int len, fifo; 977 978 state = &asc->st[asc->target]; 979 switch (ASC_PHASE(status)) { 980 case ASC_PHASE_DATAI: 981 case ASC_PHASE_DATAO: 982 ASC_TC_GET(regs, len); 983 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 984 printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n", 985 state->buflen, state->dmalen, len, fifo); 986 goto abort; 987 988 case ASC_PHASE_MSG_IN: 989 break; 990 991 case ASC_PHASE_MSG_OUT: 992 /* 993 * Check for parity error. 994 * Hardware will automatically set ATN 995 * to request the device for a MSG_OUT phase. 996 */ 997 if (state->flags & PARITY_ERR) { 998 state->flags &= ~PARITY_ERR; 999 state->msg_out = SCSI_MESSAGE_PARITY_ERROR; 1000 /* reset message in counter */ 1001 state->msglen = 0; 1002 } else 1003 state->msg_out = SCSI_NO_OP; 1004 regs->asc_fifo = state->msg_out; 1005 regs->asc_cmd = ASC_CMD_XFER_INFO; 1006 readback(regs->asc_cmd); 1007 goto done; 1008 1009 case ASC_PHASE_STATUS: 1010 /* probably an error in the SCSI command */ 1011 asc->script = &asc_scripts[SCRIPT_GET_STATUS]; 1012 regs->asc_cmd = ASC_CMD_I_COMPLETE; 1013 readback(regs->asc_cmd); 1014 goto done; 1015 1016 default: 1017 goto abort; 1018 } 1019 1020 if (state->script) 1021 goto abort; 1022 1023 /* 1024 * OK, message coming in clean up whatever is going on. 1025 * Get number of bytes left to transfered from byte counter 1026 * counter decrements when data is trf on the SCSI bus 1027 */ 1028 ASC_TC_GET(regs, len); 1029 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1030 /* flush any data in the FIFO */ 1031 if (fifo && !(state->flags & DMA_IN_PROGRESS)) { 1032 printf("asc_intr: fifo flush %d len %d fifo %x\n", fifo, len, regs->asc_fifo); 1033 regs->asc_cmd = ASC_CMD_FLUSH; 1034 readback(regs->asc_cmd); 1035 DELAY(2); 1036 } 1037 else if (fifo && state->flags & DMA_IN_PROGRESS) { 1038 if (state->flags & DMA_OUT) { 1039 len += fifo; /* Bytes dma'ed but not sent */ 1040 } 1041 else if (state->flags & DMA_IN) { 1042 printf("asc_intr: IN: dmalen %d len %d fifo %d\n", 1043 state->dmalen, len, fifo); /* XXX */ 1044 } 1045 regs->asc_cmd = ASC_CMD_FLUSH; 1046 readback(regs->asc_cmd); 1047 DELAY(2); 1048 } 1049 if (len && (state->flags & DMA_IN_PROGRESS)) { 1050 /* save number of bytes still to be sent or received */ 1051 state->dmaresid = len; 1052 state->flags &= ~DMA_IN_PROGRESS; 1053 ASC_TC_PUT(regs, 0, asc->is24bit); 1054 #ifdef DEBUG 1055 if (asc_logp == asc_log) 1056 asc_log[NLOG - 1].resid = len; 1057 else 1058 asc_logp[-1].resid = len; 1059 #endif 1060 /* setup state to resume to */ 1061 if (state->flags & DMA_IN) { 1062 /* 1063 * Since the ASC_CNFG3_SRB bit of the 1064 * cnfg3 register bit is not set, 1065 * we just transferred an extra byte. 1066 * Since we can't resume on an odd byte 1067 * boundary, we copy the valid data out 1068 * and resume DMA at the start address. 1069 */ 1070 if (len & 1) { 1071 printf("asc_intr: msg in len %d (fifo %d)\n", 1072 len, fifo); /* XXX */ 1073 len = state->dmalen - len; 1074 goto do_in; 1075 } 1076 state->script = 1077 &asc_scripts[SCRIPT_RESUME_DMA_IN]; 1078 } else if (state->flags & DMA_OUT) 1079 state->script = 1080 &asc_scripts[SCRIPT_RESUME_DMA_OUT]; 1081 else 1082 state->script = asc->script; 1083 } else if (state->flags & DMA_IN) { 1084 if (len) { 1085 #ifdef DEBUG 1086 printf("asc_intr: 1: bn %d len %d (fifo %d)\n", 1087 asc_debug_bn, len, fifo); /* XXX */ 1088 #endif 1089 goto abort; 1090 } 1091 /* setup state to resume to */ 1092 if (state->flags & DMA_IN_PROGRESS) { 1093 len = state->dmalen; 1094 state->flags &= ~DMA_IN_PROGRESS; 1095 do_in: 1096 DMA_END(asc->dma); 1097 state->buf += len; 1098 state->buflen -= len; 1099 } 1100 if (state->buflen) 1101 state->script = 1102 &asc_scripts[SCRIPT_RESUME_IN]; 1103 else 1104 state->script = 1105 &asc_scripts[SCRIPT_RESUME_NO_DATA]; 1106 } else if (state->flags & DMA_OUT) { 1107 if (len) { 1108 printf("asc_intr: 2: len %d (fifo %d)\n", len, 1109 fifo); /* XXX */ 1110 /* XXX THEO */ 1111 #if 1 1112 regs->asc_cmd = ASC_CMD_FLUSH; 1113 readback(regs->asc_cmd); 1114 DELAY(2); 1115 len = 0; 1116 #else 1117 goto abort; 1118 #endif 1119 } 1120 /* 1121 * If this is the last chunk, the next expected 1122 * state is to get status. 1123 */ 1124 if (state->flags & DMA_IN_PROGRESS) { 1125 state->flags &= ~DMA_IN_PROGRESS; 1126 DMA_END(asc->dma); 1127 len = state->dmalen; 1128 state->buf += len; 1129 state->buflen -= len; 1130 } 1131 if (state->buflen) 1132 state->script = 1133 &asc_scripts[SCRIPT_RESUME_OUT]; 1134 else 1135 state->script = 1136 &asc_scripts[SCRIPT_RESUME_NO_DATA]; 1137 } else if (asc->script == &asc_scripts[SCRIPT_SIMPLE]) 1138 state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA]; 1139 else 1140 state->script = asc->script; 1141 1142 /* setup to receive a message */ 1143 asc->script = &asc_scripts[SCRIPT_MSG_IN]; 1144 state->msglen = 0; 1145 regs->asc_cmd = ASC_CMD_XFER_INFO; 1146 readback(regs->asc_cmd); 1147 goto done; 1148 } 1149 1150 /* check for SCSI bus reset */ 1151 if (ir & ASC_INT_RESET) { 1152 register int i; 1153 1154 printf("%s: SCSI bus reset!!\n", asc->sc_dev.dv_xname); 1155 /* need to flush any pending commands */ 1156 for (i = 0; i < ASC_NCMD; i++) { 1157 if (!asc->cmd[i]) 1158 continue; 1159 asc->cmd[i]->error = XS_DRIVER_STUFFUP; 1160 asc_end(asc, 0, 0, 0); 1161 } 1162 /* rearbitrate synchronous offset */ 1163 for (i = 0; i < ASC_NCMD; i++) { 1164 asc->st[i].sync_offset = 0; 1165 asc->st[i].flags = 0; 1166 } 1167 asc->target = -1; 1168 return(1); 1169 } 1170 1171 /* check for command errors */ 1172 if (ir & ASC_INT_ILL) 1173 goto abort; 1174 1175 /* check for disconnect */ 1176 if (ir & ASC_INT_DISC) { 1177 state = &asc->st[asc->target]; 1178 switch (asc->script - asc_scripts) { 1179 case SCRIPT_DONE: 1180 case SCRIPT_DISCONNECT: 1181 /* 1182 * Disconnects can happen normally when the 1183 * command is complete with the phase being 1184 * either ASC_PHASE_DATAO or ASC_PHASE_MSG_IN. 1185 * The SCRIPT_MATCH() only checks for one phase 1186 * so we can wind up here. 1187 * Perform the appropriate operation, then proceed. 1188 */ 1189 if ((*scpt->action)(asc, status, ss, ir)) { 1190 regs->asc_cmd = scpt->command; 1191 readback(regs->asc_cmd); 1192 asc->script = scpt->next; 1193 } 1194 goto done; 1195 1196 case SCRIPT_TRY_SYNC: 1197 case SCRIPT_SIMPLE: 1198 case SCRIPT_DATA_IN: 1199 case SCRIPT_DATA_OUT: /* one of the starting scripts */ 1200 if (ASC_SS(ss) == 0) { 1201 /* device did not respond */ 1202 if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) { 1203 regs->asc_cmd = ASC_CMD_FLUSH; 1204 readback(regs->asc_cmd); 1205 } 1206 asc->cmd[asc->target]->error = XS_SELTIMEOUT; 1207 asc_end(asc, status, ss, ir); 1208 return(1); 1209 } 1210 /* FALLTHROUGH */ 1211 1212 default: 1213 printf("%s: SCSI device %d: unexpected disconnect\n", 1214 asc->sc_dev.dv_xname, asc->target); 1215 #ifdef DEBUG 1216 asc_DumpLog("asc_disc"); 1217 #endif 1218 /* 1219 * On rare occasions my RZ24 does a disconnect during 1220 * data in phase and the following seems to keep it 1221 * happy. 1222 * XXX Should a scsi disk ever do this?? 1223 */ 1224 asc->script = &asc_scripts[SCRIPT_RESEL]; 1225 asc->state = ASC_STATE_RESEL; 1226 state->flags |= DISCONN; 1227 regs->asc_cmd = ASC_CMD_ENABLE_SEL; 1228 readback(regs->asc_cmd); 1229 return(1); 1230 } 1231 } 1232 1233 /* check for reselect */ 1234 if (ir & ASC_INT_RESEL) { 1235 unsigned fifo, id, msg; 1236 1237 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1238 if (fifo < 2) 1239 goto abort; 1240 /* read unencoded SCSI ID and convert to binary */ 1241 msg = regs->asc_fifo & asc->myidmask; 1242 for (id = 0; (msg & 1) == 0; id++) 1243 msg >>= 1; 1244 /* read identify message */ 1245 msg = regs->asc_fifo; 1246 #ifdef DEBUG 1247 if (asc_logp == asc_log) 1248 asc_log[NLOG - 1].msg = msg; 1249 else 1250 asc_logp[-1].msg = msg; 1251 #endif 1252 asc->state = ASC_STATE_BUSY; 1253 asc->target = id; 1254 state = &asc->st[id]; 1255 asc->script = state->script; 1256 state->script = (script_t *)0; 1257 if (!(state->flags & DISCONN)) 1258 goto abort; 1259 state->flags &= ~DISCONN; 1260 regs->asc_syn_p = state->sync_period; 1261 regs->asc_syn_o = state->sync_offset; 1262 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1263 readback(regs->asc_cmd); 1264 goto done; 1265 } 1266 1267 /* check if we are being selected as a target */ 1268 if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN)) 1269 goto abort; 1270 1271 /* 1272 * 'ir' must be just ASC_INT_FC. 1273 * This is normal if canceling an ASC_ENABLE_SEL. 1274 */ 1275 1276 done: 1277 wbflush(); 1278 /* 1279 * If the next interrupt comes in immediatly the interrupt 1280 * dispatcher (which we are returning to) will catch it 1281 * before returning to the interrupted code. 1282 */ 1283 return(1); 1284 1285 abort: 1286 #ifdef DEBUG 1287 asc_DumpLog("asc_intr"); 1288 #endif 1289 panic("asc_intr"); 1290 return(1); 1291 } 1292 1293 /* 1294 * All the many little things that the interrupt 1295 * routine might switch to. 1296 */ 1297 1298 /* ARGSUSED */ 1299 static int 1300 script_nop(asc, status, ss, ir) 1301 asc_softc_t asc; 1302 int status, ss, ir; 1303 { 1304 return (1); 1305 } 1306 1307 /* ARGSUSED */ 1308 static int 1309 asc_get_status(asc, status, ss, ir) 1310 register asc_softc_t asc; 1311 register int status, ss, ir; 1312 { 1313 register asc_regmap_t *regs = asc->regs; 1314 register int data; 1315 1316 /* 1317 * Get the last two bytes in the FIFO. 1318 */ 1319 if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) { 1320 printf("asc_get_status: cmdreg %x, fifo cnt %d\n", 1321 regs->asc_cmd, data); /* XXX */ 1322 #ifdef DEBUG 1323 asc_DumpLog("get_status"); /* XXX */ 1324 #endif 1325 if (data < 2) { 1326 asc->regs->asc_cmd = ASC_CMD_MSG_ACPT; 1327 readback(asc->regs->asc_cmd); 1328 return (0); 1329 } 1330 do { 1331 data = regs->asc_fifo; 1332 } while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2); 1333 } 1334 1335 /* save the status byte */ 1336 asc->st[asc->target].statusByte = data = regs->asc_fifo; 1337 #ifdef DEBUG 1338 if (asc_logp == asc_log) 1339 asc_log[NLOG - 1].msg = data; 1340 else 1341 asc_logp[-1].msg = data; 1342 #endif 1343 1344 /* get the (presumed) command_complete message */ 1345 if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE) 1346 return (1); 1347 1348 #ifdef DEBUG 1349 printf("asc_get_status: status %x cmd %x\n", 1350 asc->st[asc->target].statusByte, data); 1351 asc_DumpLog("asc_get_status"); 1352 #endif 1353 return (0); 1354 } 1355 1356 /* ARGSUSED */ 1357 static int 1358 asc_end(asc, status, ss, ir) 1359 asc_softc_t asc; 1360 int status, ss, ir; 1361 { 1362 struct scsipi_xfer *scsicmd; 1363 struct scsipi_periph *periph; 1364 State *state; 1365 int i, target; 1366 1367 asc->state = ASC_STATE_IDLE; 1368 target = asc->target; 1369 asc->target = -1; 1370 scsicmd = asc->cmd[target]; 1371 periph = scsicmd->xs_periph; 1372 asc->cmd[target] = (struct scsipi_xfer *)0; 1373 state = &asc->st[target]; 1374 1375 #ifdef DEBUG 1376 if (asc_debug > 1) { 1377 printf("asc_end: %s target %d cmd %x err %d resid %d\n", 1378 asc->sc_dev.dv_xname, target, 1379 state->cmd.opcode, scsicmd->error, state->buflen); 1380 } 1381 #endif 1382 #ifdef DIAGNOSTIC 1383 if (target < 0 || !scsicmd) 1384 panic("asc_end"); 1385 #endif 1386 1387 /* look for disconnected devices */ 1388 for (i = 0; i < ASC_NCMD; i++) { 1389 if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN)) 1390 continue; 1391 asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL; 1392 readback(asc->regs->asc_cmd); 1393 asc->state = ASC_STATE_RESEL; 1394 asc->script = &asc_scripts[SCRIPT_RESEL]; 1395 break; 1396 } 1397 1398 if(scsicmd->error == XS_NOERROR) { 1399 if((state->statusByte & ST_MASK) == SCSI_CHECK) { 1400 scsicmd->status = state->statusByte; 1401 scsicmd->error = XS_BUSY; 1402 } 1403 } 1404 1405 scsicmd->resid = state->buflen; 1406 1407 /* 1408 * Look for another device that is ready. 1409 * May want to keep last one started and increment for fairness 1410 * rather than always starting at zero. 1411 */ 1412 for (i = 0; i < ASC_NCMD; i++) { 1413 /* don't restart a disconnected command */ 1414 if (!asc->cmd[i] || (asc->st[i].flags & DISCONN)) 1415 continue; 1416 asc_startcmd(asc, i); 1417 break; 1418 } 1419 1420 /* signal device driver that the command is done */ 1421 scsipi_done(scsicmd); 1422 1423 return (0); 1424 } 1425 1426 /* ARGSUSED */ 1427 static int 1428 asc_dma_in(asc, status, ss, ir) 1429 register asc_softc_t asc; 1430 register int status, ss, ir; 1431 { 1432 register asc_regmap_t *regs = asc->regs; 1433 register State *state = &asc->st[asc->target]; 1434 register int len; 1435 1436 /* check for previous chunk in buffer */ 1437 if (state->flags & DMA_IN_PROGRESS) { 1438 /* 1439 * Only count bytes that have been copied to memory. 1440 * There may be some bytes in the FIFO if synchonous transfers 1441 * are in progress. 1442 */ 1443 DMA_END(asc->dma); 1444 ASC_TC_GET(regs, len); 1445 len = state->dmalen - len; 1446 state->buf += len; 1447 state->buflen -= len; 1448 } 1449 1450 /* setup to start reading the next chunk */ 1451 len = state->buflen; 1452 #ifdef DEBUG 1453 if (asc_logp == asc_log) 1454 asc_log[NLOG - 1].resid = len; 1455 else 1456 asc_logp[-1].resid = len; 1457 #endif 1458 if (len > state->dmaBufSize) 1459 len = state->dmaBufSize; 1460 state->dmalen = len; 1461 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV); 1462 ASC_TC_PUT(regs, len, asc->is24bit); 1463 #ifdef DEBUG 1464 if (asc_debug > 2) 1465 printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len); 1466 #endif 1467 1468 /* check for next chunk */ 1469 state->flags |= DMA_IN_PROGRESS; 1470 if (len != state->buflen) { 1471 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1472 readback(regs->asc_cmd); 1473 asc->script = &asc_scripts[SCRIPT_CONTINUE_IN]; 1474 return (0); 1475 } 1476 return (1); 1477 } 1478 1479 /* ARGSUSED */ 1480 static int 1481 asc_last_dma_in(asc, status, ss, ir) 1482 register asc_softc_t asc; 1483 register int status, ss, ir; 1484 { 1485 register asc_regmap_t *regs = asc->regs; 1486 register State *state = &asc->st[asc->target]; 1487 register int len, fifo; 1488 1489 DMA_END(asc->dma); 1490 ASC_TC_GET(regs, len); 1491 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1492 #ifdef DEBUG 1493 if (asc_debug > 2) 1494 printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n", 1495 state->buflen, state->dmalen, len, fifo); 1496 #endif 1497 if (fifo) { 1498 /* device must be trying to send more than we expect */ 1499 regs->asc_cmd = ASC_CMD_FLUSH; 1500 readback(regs->asc_cmd); 1501 } 1502 state->flags &= ~DMA_IN_PROGRESS; 1503 len = state->dmalen - len; 1504 state->buflen -= len; 1505 1506 return (1); 1507 } 1508 1509 /* ARGSUSED */ 1510 static int 1511 asc_resume_in(asc, status, ss, ir) 1512 register asc_softc_t asc; 1513 register int status, ss, ir; 1514 { 1515 register asc_regmap_t *regs = asc->regs; 1516 register State *state = &asc->st[asc->target]; 1517 register int len; 1518 1519 /* setup to start reading the next chunk */ 1520 len = state->buflen; 1521 #ifdef DEBUG 1522 if (asc_logp == asc_log) 1523 asc_log[NLOG - 1].resid = len; 1524 else 1525 asc_logp[-1].resid = len; 1526 #endif 1527 if (len > state->dmaBufSize) 1528 len = state->dmaBufSize; 1529 state->dmalen = len; 1530 #ifdef DEBUG 1531 if (asc_logp == asc_log) 1532 asc_log[NLOG - 1].resid = len; 1533 else 1534 asc_logp[-1].resid = len; 1535 #endif 1536 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV); 1537 ASC_TC_PUT(regs, len, asc->is24bit); 1538 #ifdef DEBUG 1539 if (asc_debug > 2) 1540 printf("asc_resume_in: buflen %d, len %d\n", state->buflen, 1541 len); 1542 #endif 1543 1544 /* check for next chunk */ 1545 state->flags |= DMA_IN_PROGRESS; 1546 if (len != state->buflen) { 1547 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1548 readback(regs->asc_cmd); 1549 asc->script = &asc_scripts[SCRIPT_CONTINUE_IN]; 1550 return (0); 1551 } 1552 return (1); 1553 } 1554 1555 /* ARGSUSED */ 1556 static int 1557 asc_resume_dma_in(asc, status, ss, ir) 1558 register asc_softc_t asc; 1559 register int status, ss, ir; 1560 { 1561 register asc_regmap_t *regs = asc->regs; 1562 register State *state = &asc->st[asc->target]; 1563 register int len, off; 1564 1565 /* setup to finish reading the current chunk */ 1566 len = state->dmaresid; 1567 off = state->dmalen - len; 1568 if ((off & 1) && state->sync_offset) { 1569 printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n", 1570 state->dmalen, len, off); /* XXX */ 1571 regs->asc_res_fifo = ((u_char *)state->buf)[off]; 1572 /*XXX Need to flush cache ? */ 1573 } 1574 DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_FROM_DEV); 1575 ASC_TC_PUT(regs, len, asc->is24bit); 1576 #ifdef DEBUG 1577 if (asc_debug > 2) 1578 printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n", 1579 state->dmalen, state->buflen, len, off); 1580 #endif 1581 1582 /* check for next chunk */ 1583 state->flags |= DMA_IN_PROGRESS; 1584 if (state->dmalen != state->buflen) { 1585 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1586 readback(regs->asc_cmd); 1587 asc->script = &asc_scripts[SCRIPT_CONTINUE_IN]; 1588 return (0); 1589 } 1590 return (1); 1591 } 1592 1593 /* ARGSUSED */ 1594 static int 1595 asc_dma_out(asc, status, ss, ir) 1596 register asc_softc_t asc; 1597 register int status, ss, ir; 1598 { 1599 register asc_regmap_t *regs = asc->regs; 1600 register State *state = &asc->st[asc->target]; 1601 register int len, fifo; 1602 1603 if (state->flags & DMA_IN_PROGRESS) { 1604 /* check to be sure previous chunk was finished */ 1605 ASC_TC_GET(regs, len); 1606 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1607 if (len || fifo) 1608 printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n", 1609 state->buflen, state->dmalen, len, fifo); /* XXX */ 1610 len += fifo; 1611 len = state->dmalen - len; 1612 state->buf += len; 1613 state->buflen -= len; 1614 } 1615 1616 /* setup for this chunk */ 1617 len = state->buflen; 1618 #ifdef DEBUG 1619 if (asc_logp == asc_log) 1620 asc_log[NLOG - 1].resid = len; 1621 else 1622 asc_logp[-1].resid = len; 1623 #endif 1624 if (len > state->dmaBufSize) 1625 len = state->dmaBufSize; 1626 state->dmalen = len; 1627 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV); 1628 ASC_TC_PUT(regs, len, asc->is24bit); 1629 #ifdef DEBUG 1630 if (asc_debug > 2) 1631 printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len); 1632 #endif 1633 1634 /* check for next chunk */ 1635 state->flags |= DMA_IN_PROGRESS; 1636 if (len != state->buflen) { 1637 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1638 readback(regs->asc_cmd); 1639 asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT]; 1640 return (0); 1641 } 1642 return (1); 1643 } 1644 1645 /* ARGSUSED */ 1646 static int 1647 asc_last_dma_out(asc, status, ss, ir) 1648 register asc_softc_t asc; 1649 register int status, ss, ir; 1650 { 1651 register asc_regmap_t *regs = asc->regs; 1652 register State *state = &asc->st[asc->target]; 1653 register int len, fifo; 1654 1655 ASC_TC_GET(regs, len); 1656 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1657 #ifdef DEBUG 1658 if (asc_debug > 2) 1659 printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n", 1660 state->buflen, state->dmalen, len, fifo); 1661 #endif 1662 if (fifo) { 1663 len += fifo; 1664 regs->asc_cmd = ASC_CMD_FLUSH; 1665 readback(regs->asc_cmd); 1666 } 1667 state->flags &= ~DMA_IN_PROGRESS; 1668 len = state->dmalen - len; 1669 state->buflen -= len; 1670 return (1); 1671 } 1672 1673 /* ARGSUSED */ 1674 static int 1675 asc_resume_out(asc, status, ss, ir) 1676 register asc_softc_t asc; 1677 register int status, ss, ir; 1678 { 1679 register asc_regmap_t *regs = asc->regs; 1680 register State *state = &asc->st[asc->target]; 1681 register int len; 1682 1683 /* setup for this chunk */ 1684 len = state->buflen; 1685 #ifdef DEBUG 1686 if (asc_logp == asc_log) 1687 asc_log[NLOG - 1].resid = len; 1688 else 1689 asc_logp[-1].resid = len; 1690 #endif 1691 if (len > state->dmaBufSize) 1692 len = state->dmaBufSize; 1693 state->dmalen = len; 1694 #ifdef DEBUG 1695 if (asc_logp == asc_log) 1696 asc_log[NLOG - 1].resid = len; 1697 else 1698 asc_logp[-1].resid = len; 1699 #endif 1700 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV); 1701 ASC_TC_PUT(regs, len, asc->is24bit); 1702 #ifdef DEBUG 1703 if (asc_debug > 2) 1704 printf("asc_resume_out: buflen %d, len %d\n", state->buflen, 1705 len); 1706 #endif 1707 1708 /* check for next chunk */ 1709 state->flags |= DMA_IN_PROGRESS; 1710 if (len != state->buflen) { 1711 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1712 readback(regs->asc_cmd); 1713 asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT]; 1714 return (0); 1715 } 1716 return (1); 1717 } 1718 1719 /* ARGSUSED */ 1720 static int 1721 asc_resume_dma_out(asc, status, ss, ir) 1722 register asc_softc_t asc; 1723 register int status, ss, ir; 1724 { 1725 register asc_regmap_t *regs = asc->regs; 1726 register State *state = &asc->st[asc->target]; 1727 register int len, off; 1728 1729 /* setup to finish writing this chunk */ 1730 len = state->dmaresid; 1731 off = state->dmalen - len; 1732 if (off & 1) { 1733 printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n", 1734 state->dmalen, len, off); /* XXX */ 1735 regs->asc_fifo = ((u_char *)state->buf)[off]; 1736 /*XXX Need to flush Cache ? */ 1737 off++; 1738 len--; 1739 } 1740 DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_TO_DEV); 1741 ASC_TC_PUT(regs, len, asc->is24bit); 1742 #ifdef DEBUG 1743 if (asc_debug > 2) 1744 printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n", 1745 state->dmalen, state->buflen, len, off); 1746 #endif 1747 1748 /* check for next chunk */ 1749 state->flags |= DMA_IN_PROGRESS; 1750 if (state->dmalen != state->buflen) { 1751 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1752 readback(regs->asc_cmd); 1753 asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT]; 1754 return (0); 1755 } 1756 return (1); 1757 } 1758 1759 /* ARGSUSED */ 1760 static int 1761 asc_sendsync(asc, status, ss, ir) 1762 register asc_softc_t asc; 1763 register int status, ss, ir; 1764 { 1765 register asc_regmap_t *regs = asc->regs; 1766 register State *state = &asc->st[asc->target]; 1767 1768 /* send the extended synchronous negotiation message */ 1769 regs->asc_fifo = SCSI_EXTENDED_MSG; 1770 wbflush(); 1771 regs->asc_fifo = 3; 1772 wbflush(); 1773 regs->asc_fifo = SCSI_SYNCHRONOUS_XFER; 1774 wbflush(); 1775 regs->asc_fifo = SCSI_MIN_PERIOD; 1776 wbflush(); 1777 regs->asc_fifo = ASC_MAX_OFFSET; 1778 /* state to resume after we see the sync reply message */ 1779 state->script = asc->script + 2; 1780 state->msglen = 0; 1781 return (1); 1782 } 1783 1784 /* ARGSUSED */ 1785 static int 1786 asc_replysync(asc, status, ss, ir) 1787 register asc_softc_t asc; 1788 register int status, ss, ir; 1789 { 1790 register asc_regmap_t *regs = asc->regs; 1791 register State *state = &asc->st[asc->target]; 1792 1793 #ifdef DEBUG 1794 if (asc_debug > 2) 1795 printf("asc_replysync: %x %x\n", 1796 asc_to_scsi_period[state->sync_period] * asc->tb_ticks, 1797 state->sync_offset); 1798 #endif 1799 /* send synchronous transfer in response to a request */ 1800 regs->asc_fifo = SCSI_EXTENDED_MSG; 1801 wbflush(); 1802 regs->asc_fifo = 3; 1803 wbflush(); 1804 regs->asc_fifo = SCSI_SYNCHRONOUS_XFER; 1805 wbflush(); 1806 regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks; 1807 wbflush(); 1808 regs->asc_fifo = state->sync_offset; 1809 regs->asc_cmd = ASC_CMD_XFER_INFO; 1810 readback(regs->asc_cmd); 1811 1812 /* return to the appropriate script */ 1813 if (!state->script) { 1814 #ifdef DEBUG 1815 asc_DumpLog("asc_replsync"); 1816 #endif 1817 panic("asc_replysync"); 1818 } 1819 asc->script = state->script; 1820 state->script = (script_t *)0; 1821 return (0); 1822 } 1823 1824 /* ARGSUSED */ 1825 static int 1826 asc_msg_in(asc, status, ss, ir) 1827 register asc_softc_t asc; 1828 register int status, ss, ir; 1829 { 1830 register asc_regmap_t *regs = asc->regs; 1831 register State *state = &asc->st[asc->target]; 1832 register int msg; 1833 int i; 1834 1835 /* read one message byte */ 1836 msg = regs->asc_fifo; 1837 #ifdef DEBUG 1838 if (asc_logp == asc_log) 1839 asc_log[NLOG - 1].msg = msg; 1840 else 1841 asc_logp[-1].msg = msg; 1842 #endif 1843 1844 /* check for multi-byte message */ 1845 if (state->msglen != 0) { 1846 /* first byte is the message length */ 1847 if (state->msglen < 0) { 1848 state->msglen = msg; 1849 return (1); 1850 } 1851 if (state->msgcnt >= state->msglen) 1852 goto abort; 1853 state->msg_in[state->msgcnt++] = msg; 1854 1855 /* did we just read the last byte of the message? */ 1856 if (state->msgcnt != state->msglen) 1857 return (1); 1858 1859 /* process an extended message */ 1860 #ifdef DEBUG 1861 if (asc_debug > 2) 1862 printf("asc_msg_in: msg %x %x %x\n", 1863 state->msg_in[0], 1864 state->msg_in[1], 1865 state->msg_in[2]); 1866 #endif 1867 switch (state->msg_in[0]) { 1868 case SCSI_SYNCHRONOUS_XFER: 1869 state->flags |= DID_SYNC; 1870 state->sync_offset = state->msg_in[2]; 1871 1872 /* convert SCSI period to ASC period */ 1873 i = state->msg_in[1] / asc->tb_ticks; 1874 if (i < asc->min_period) 1875 i = asc->min_period; 1876 else if (i >= asc->max_period) { 1877 /* can't do sync transfer, period too long */ 1878 printf("%s: SCSI device %d: sync xfer period too long (%d)\n", 1879 asc->sc_dev.dv_xname, asc->target, i); 1880 i = asc->max_period; 1881 state->sync_offset = 0; 1882 } 1883 if ((i * asc->tb_ticks) != state->msg_in[1]) 1884 i++; 1885 state->sync_period = i & 0x1F; 1886 1887 /* 1888 * If this is a request, check minimums and 1889 * send back an acknowledge. 1890 */ 1891 if (!(state->flags & TRY_SYNC)) { 1892 regs->asc_cmd = ASC_CMD_SET_ATN; 1893 readback(regs->asc_cmd); 1894 1895 if (state->sync_period < asc->min_period) 1896 state->sync_period = 1897 asc->min_period; 1898 if (state->sync_offset > ASC_MAX_OFFSET) 1899 state->sync_offset = 1900 ASC_MAX_OFFSET; 1901 asc->script = &asc_scripts[SCRIPT_REPLY_SYNC]; 1902 regs->asc_syn_p = state->sync_period; 1903 readback(regs->asc_syn_p); 1904 regs->asc_syn_o = state->sync_offset; 1905 readback(regs->asc_syn_o); 1906 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1907 readback(regs->asc_cmd); 1908 return (0); 1909 } 1910 1911 regs->asc_syn_p = state->sync_period; 1912 readback(regs->asc_syn_p); 1913 regs->asc_syn_o = state->sync_offset; 1914 readback(regs->asc_syn_o); 1915 goto done; 1916 1917 default: 1918 printf("%s: SCSI device %d: rejecting extended message 0x%x\n", 1919 asc->sc_dev.dv_xname, asc->target, 1920 state->msg_in[0]); 1921 goto reject; 1922 } 1923 } 1924 1925 /* process first byte of a message */ 1926 #ifdef DEBUG 1927 if (asc_debug > 2) 1928 printf("asc_msg_in: msg %x\n", msg); 1929 #endif 1930 switch (msg) { 1931 #if 0 1932 case SCSI_MESSAGE_REJECT: 1933 printf(" did not like SYNCH xfer "); /* XXX */ 1934 state->flags |= DID_SYNC; 1935 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1936 readback(regs->asc_cmd); 1937 status = asc_wait(regs, ASC_CSR_INT); 1938 ir = regs->asc_intr; 1939 /* some just break out here, some dont */ 1940 if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) { 1941 regs->asc_fifo = SCSI_ABORT; 1942 regs->asc_cmd = ASC_CMD_XFER_INFO; 1943 readback(regs->asc_cmd); 1944 status = asc_wait(regs, ASC_CSR_INT); 1945 ir = regs->asc_intr; 1946 } 1947 if (ir & ASC_INT_DISC) { 1948 asc_end(asc, status, 0, ir); 1949 return (0); 1950 } 1951 goto status; 1952 #endif /* 0 */ 1953 1954 case SCSI_EXTENDED_MSG: /* read an extended message */ 1955 /* setup to read message length next */ 1956 state->msglen = -1; 1957 state->msgcnt = 0; 1958 return (1); 1959 1960 case SCSI_NO_OP: 1961 break; 1962 1963 case SCSI_SAVE_DATA_POINTER: 1964 /* expect another message */ 1965 return (1); 1966 1967 case SCSI_RESTORE_POINTERS: 1968 /* 1969 * Need to do the following if resuming synchonous data in 1970 * on an odd byte boundary. 1971 regs->asc_cnfg2 |= ASC_CNFG2_RFB; 1972 */ 1973 break; 1974 1975 case SCSI_DISCONNECT: 1976 if (state->flags & DISCONN) 1977 goto abort; 1978 state->flags |= DISCONN; 1979 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1980 readback(regs->asc_cmd); 1981 asc->script = &asc_scripts[SCRIPT_DISCONNECT]; 1982 return (0); 1983 1984 default: 1985 printf("%s: SCSI device %d: rejecting message 0x%x\n", 1986 asc->sc_dev.dv_xname, asc->target, msg); 1987 reject: 1988 /* request a message out before acknowledging this message */ 1989 state->msg_out = SCSI_MESSAGE_REJECT; 1990 regs->asc_cmd = ASC_CMD_SET_ATN; 1991 readback(regs->asc_cmd); 1992 } 1993 1994 done: 1995 /* return to original script */ 1996 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1997 readback(regs->asc_cmd); 1998 if (!state->script) { 1999 abort: 2000 #ifdef DEBUG 2001 asc_DumpLog("asc_msg_in"); 2002 #endif 2003 panic("asc_msg_in"); 2004 } 2005 asc->script = state->script; 2006 state->script = (script_t *)0; 2007 return (0); 2008 } 2009 2010 /* ARGSUSED */ 2011 static int 2012 asc_disconnect(asc, status, ss, ir) 2013 asc_softc_t asc; 2014 int status, ss, ir; 2015 { 2016 #ifdef DIAGNOSTIC 2017 if (!(asc->st[asc->target].flags & DISCONN)) { 2018 printf("asc_disconnect: device %d: DISCONN not set!\n", 2019 asc->target); 2020 } 2021 #endif /* DIAGNOSTIC */ 2022 asc->target = -1; 2023 asc->state = ASC_STATE_RESEL; 2024 return (1); 2025 } 2026 2027 #ifdef DEBUG 2028 /* 2029 * Dump the log buffer. 2030 */ 2031 static void 2032 asc_DumpLog(str) 2033 char *str; 2034 { 2035 register struct asc_log *lp; 2036 register u_int status; 2037 2038 printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd, 2039 asc_debug_bn, asc_debug_sz); 2040 lp = asc_logp; 2041 do { 2042 status = lp->status; 2043 printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n", 2044 status >> 24, 2045 lp->target, 2046 (status >> 16) & 0xFF, 2047 (status >> 8) & 0xFF, 2048 status & 0XFF, 2049 lp->state, 2050 asc_scripts[lp->state].condition, 2051 lp->msg, lp->resid); 2052 if (++lp >= &asc_log[NLOG]) 2053 lp = asc_log; 2054 } while (lp != asc_logp); 2055 } 2056 #endif /* DEBUG */ 2057