1 /* $NetBSD: asc.c,v 1.8 2002/10/02 04:59:48 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 CFATTACH_DECL(asc, sizeof(struct asc_softc), 498 ascmatch, ascattach, NULL, NULL); 499 500 /* 501 * Glue to the machine dependent scsi 502 */ 503 void asc_scsipi_request __P((struct scsipi_channel *, 504 scsipi_adapter_req_t, void *)); 505 506 static int asc_intr __P((void *)); 507 static void asc_poll __P((struct asc_softc *, int)); 508 #ifdef DEBUG 509 static void asc_DumpLog __P((char *)); 510 #endif 511 512 /* 513 * Match driver based on name 514 */ 515 int 516 ascmatch(parent, match, aux) 517 struct device *parent; 518 struct cfdata *match; 519 void *aux; 520 { 521 struct jazzio_attach_args *ja = aux; 522 523 if(strcmp(ja->ja_name, "asc") != 0) 524 return (0); 525 return (1); 526 } 527 528 void 529 ascattach(parent, self, aux) 530 struct device *parent; 531 struct device *self; 532 void *aux; 533 { 534 struct jazzio_attach_args *ja = aux; 535 asc_softc_t asc = (void *)self; 536 asc_regmap_t *regs; 537 int id, s, i; 538 int bufsiz; 539 540 if (asc_conf == NULL) 541 panic("asc_conf isn't initialized"); 542 543 /* 544 * Initialize hw descriptor, cache some pointers 545 */ 546 asc->regs = (asc_regmap_t *)ja->ja_addr; /* XXX */ 547 548 /* 549 * Set up machine dependencies. 550 * 1) how to do dma 551 * 2) timing based on chip clock frequency 552 */ 553 #if 1 /*XXX check if code handles 0 as 64k */ 554 bufsiz = 63 * 1024; 555 #else 556 bufsiz = 64 * 1024; 557 #endif 558 asc->dma = &asc->__dma; 559 asc_dma_init(asc->dma); 560 561 /* 562 * Now for timing. 563 */ 564 asc->min_period = asc_conf->ac_timing->min_period; 565 asc->max_period = asc_conf->ac_timing->max_period; 566 asc->ccf = asc_conf->ac_timing->ccf; 567 asc->timeout_250 = asc_conf->ac_timing->timeout_250; 568 asc->tb_ticks = asc_conf->ac_timing->tb_ticks; 569 570 asc->state = ASC_STATE_IDLE; 571 asc->target = -1; 572 573 regs = asc->regs; 574 575 /* 576 * Reset chip, fully. Note that interrupts are already enabled. 577 */ 578 s = splbio(); 579 580 /* preserve our ID for now */ 581 asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID; 582 asc->myidmask = ~(1 << asc->sc_id); 583 584 /* identify 53CF9x-2 or not */ 585 regs->asc_cmd = ASC_CMD_RESET; 586 wbflush(); DELAY(25); 587 regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP; 588 wbflush(); DELAY(25); 589 regs->asc_cnfg2 = ASC_CNFG2_FE; 590 wbflush(); DELAY(25); 591 regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP; 592 wbflush(); DELAY(25); 593 asc->is24bit = regs->asc_id == ASC_ID_53CF94; 594 595 asc_reset(asc, regs); 596 597 /* 598 * Our SCSI id on the bus. 599 * The user can set this via the prom on 3maxen/picaen. 600 * If this changes it is easy to fix: make a default that 601 * can be changed as boot arg. 602 */ 603 #ifdef unneeded 604 regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) | 605 (scsi_initiator_id[unit] & 0x7); 606 asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID; 607 #endif 608 id = asc->sc_id; 609 splx(s); 610 611 /* 612 * Give each target its DMA buffer region. 613 * The buffer address is the same for all targets, 614 * the allocated dma viritual scatter/gather space. 615 */ 616 for (i = 0; i < ASC_NCMD; i++) { 617 asc->st[i].dmaBufSize = bufsiz; 618 } 619 620 /* 621 * Set up interrupt handler. 622 */ 623 jazzio_intr_establish(ja->ja_intr, asc_intr, (void *)asc); 624 625 printf(": %s, target %d\n", asc->is24bit ? "NCR53CF9X-2" : "NCR53C94", 626 id); 627 628 asc->sc_adapter.adapt_dev = &asc->sc_dev; 629 asc->sc_adapter.adapt_nchannels = 1; 630 asc->sc_adapter.adapt_openings = 7; 631 asc->sc_adapter.adapt_max_periph = 1; 632 asc->sc_adapter.adapt_ioctl = NULL; 633 asc->sc_adapter.adapt_minphys = minphys; 634 asc->sc_adapter.adapt_request = asc_scsipi_request; 635 636 memset(&asc->sc_channel, 0, sizeof(asc->sc_channel)); 637 asc->sc_channel.chan_adapter = &asc->sc_adapter; 638 asc->sc_channel.chan_bustype = &scsi_bustype; 639 asc->sc_channel.chan_channel = 0; 640 asc->sc_channel.chan_ntargets = 8; 641 asc->sc_channel.chan_nluns = 8; 642 asc->sc_channel.chan_id = asc->sc_id; 643 644 /* 645 * Now try to attach all the sub devices. 646 */ 647 config_found(self, &asc->sc_channel, scsiprint); 648 } 649 650 /* 651 * Start activity on a SCSI device. 652 * We maintain information on each device separately since devices can 653 * connect/disconnect during an operation. 654 */ 655 void 656 asc_scsipi_request(chan, req, arg) 657 struct scsipi_channel *chan; 658 scsipi_adapter_req_t req; 659 void *arg; 660 { 661 struct scsipi_xfer *xs; 662 struct scsipi_periph *periph; 663 struct asc_softc *asc = (void *)chan->chan_adapter->adapt_dev; 664 int dontqueue, s; 665 666 switch (req) { 667 case ADAPTER_REQ_RUN_XFER: 668 xs = arg; 669 periph = xs->xs_periph; 670 671 dontqueue = xs->xs_control & XS_CTL_POLL; 672 673 /* 674 * Flush caches for any data buffer 675 */ 676 if(xs->datalen != 0) { 677 mips_dcache_wbinv_range((vaddr_t)xs->data, xs->datalen); 678 } 679 /* 680 * The hack on the next few lines are to avoid buffers 681 * mapped to UADDR. Realloc to the kva uarea address. 682 */ 683 if((u_int)(xs->data) >= UADDR) { 684 xs->data = ((u_int)(xs->data) & ~UADDR) + (u_char *)(curproc->p_addr); 685 } 686 687 s = splbio(); 688 asc->cmd[periph->periph_target] = xs; 689 690 /* 691 * Going to launch. 692 * Make a local copy of the command and some pointers. 693 */ 694 asc_startcmd(asc, periph->periph_target); 695 696 /* 697 * If in startup, interrupts not usable yet. 698 */ 699 if(dontqueue) { 700 asc_poll(asc,periph->periph_target); 701 } 702 splx(s); 703 return; 704 case ADAPTER_REQ_GROW_RESOURCES: 705 /* XXX Not supported. */ 706 return; 707 case ADAPTER_REQ_SET_XFER_MODE: 708 /* XXX Not supported. */ 709 return; 710 } 711 } 712 713 void 714 asc_poll(asc, target) 715 struct asc_softc *asc; 716 int target; 717 { 718 struct scsipi_xfer *scsicmd = asc->cmd[target]; 719 int count = scsicmd->timeout * 10; 720 721 while(count) { 722 if(asc->regs->asc_status &ASC_CSR_INT) { 723 asc_intr(asc); 724 } 725 if(scsicmd->xs_status & XS_STS_DONE) 726 break; 727 DELAY(5); 728 count--; 729 } 730 if(count == 0) { 731 scsicmd->error = XS_TIMEOUT; 732 asc_end(asc, 0, 0, 0); 733 } 734 } 735 736 static void 737 asc_reset(asc, regs) 738 asc_softc_t asc; 739 asc_regmap_t *regs; 740 { 741 742 /* 743 * Reset chip and wait till done 744 */ 745 regs->asc_cmd = ASC_CMD_RESET; 746 wbflush(); DELAY(25); 747 748 /* spec says this is needed after reset */ 749 regs->asc_cmd = ASC_CMD_NOP; 750 wbflush(); DELAY(25); 751 752 /* 753 * Set up various chip parameters 754 */ 755 regs->asc_ccf = asc->ccf; 756 wbflush(); DELAY(25); 757 regs->asc_sel_timo = asc->timeout_250; 758 /* restore our ID */ 759 regs->asc_cnfg1 = asc->sc_id | ASC_CNFG1_P_CHECK; 760 /* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */ 761 regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL; 762 regs->asc_cnfg3 = asc_conf->ac_cnfg3; 763 /* zero anything else */ 764 ASC_TC_PUT(regs, 0, asc->is24bit); 765 regs->asc_syn_p = asc->min_period; 766 regs->asc_syn_o = 0; /* async for now */ 767 wbflush(); 768 } 769 770 /* 771 * Start a SCSI command on a target. 772 */ 773 static void 774 asc_startcmd(asc, target) 775 asc_softc_t asc; 776 int target; 777 { 778 asc_regmap_t *regs; 779 State *state; 780 struct scsipi_xfer *scsicmd; 781 int i, len; 782 783 /* 784 * See if another target is currently selected on this SCSI bus. 785 */ 786 if (asc->target >= 0) 787 return; 788 789 regs = asc->regs; 790 791 /* 792 * If a reselection is in progress, it is Ok to ignore it since 793 * the ASC will automatically cancel the command and flush 794 * the FIFO if the ASC is reselected before the command starts. 795 * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if 796 * a reselect occurs before starting the command. 797 */ 798 799 asc->state = ASC_STATE_BUSY; 800 asc->target = target; 801 802 /* cache some pointers */ 803 scsicmd = asc->cmd[target]; 804 state = &asc->st[target]; 805 806 /* 807 * Init the chip and target state. 808 */ 809 state->flags = state->flags & DID_SYNC; 810 state->script = (script_t *)0; 811 state->msg_out = SCSI_NO_OP; 812 813 /* 814 * Set up for DMA of command output. Also need to flush cache. 815 */ 816 bcopy(scsicmd->cmd, &state->cmd, scsicmd->cmdlen); 817 state->cmdlen = scsicmd->cmdlen; 818 state->buf = (vaddr_t)scsicmd->data; 819 state->buflen = scsicmd->datalen; 820 len = state->cmdlen; 821 state->dmalen = len; 822 823 #ifdef DEBUG 824 if (asc_debug > 1) { 825 printf("asc_startcmd: %s target %d cmd %x len %d\n", 826 asc->sc_dev.dv_xname, target, 827 state->cmd.opcode, state->buflen); 828 } 829 #endif 830 831 /* check for simple SCSI command with no data transfer */ 832 if (scsicmd->xs_control & XS_CTL_DATA_OUT) { 833 asc->script = &asc_scripts[SCRIPT_DATA_OUT]; 834 state->flags |= DMA_OUT; 835 } 836 else if (scsicmd->xs_control & XS_CTL_DATA_IN) { 837 asc->script = &asc_scripts[SCRIPT_DATA_IN]; 838 state->flags |= DMA_IN; 839 } 840 else if (state->buflen == 0) { 841 /* check for sync negotiation */ 842 if ((scsicmd->xs_status & /* SCSICMD_USE_SYNC */ 0) && 843 !(state->flags & DID_SYNC)) { 844 asc->script = &asc_scripts[SCRIPT_TRY_SYNC]; 845 state->flags |= TRY_SYNC; 846 } else 847 asc->script = &asc_scripts[SCRIPT_SIMPLE]; 848 state->buf = (vaddr_t)0; 849 } 850 851 #ifdef DEBUG 852 asc_debug_cmd = state->cmd.opcode; 853 if (state->cmd.opcode == SCSI_READ_EXT) { 854 asc_debug_bn = (state->cmd.bytes[1] << 24) | 855 (state->cmd.bytes[2] << 16) | 856 (state->cmd.bytes[3] << 8) | 857 state->cmd.bytes[4]; 858 asc_debug_sz = (state->cmd.bytes[6] << 8) | state->cmd.bytes[7]; 859 } 860 asc_logp->status = PACK(asc->sc_dev.dv_unit, 0, 0, asc_debug_cmd); 861 asc_logp->target = asc->target; 862 asc_logp->state = asc->script - asc_scripts; 863 asc_logp->msg = SCSI_DIS_REC_IDENTIFY; 864 asc_logp->resid = scsicmd->datalen; 865 if (++asc_logp >= &asc_log[NLOG]) 866 asc_logp = asc_log; 867 #endif 868 869 /* preload the FIFO with the message and command to be sent */ 870 regs->asc_fifo = SCSI_DIS_REC_IDENTIFY | 871 (scsicmd->xs_periph->periph_lun & 0x07); 872 873 for( i = 0; i < len; i++ ) { 874 regs->asc_fifo = ((caddr_t)&state->cmd)[i]; 875 } 876 ASC_TC_PUT(regs, 0, asc->is24bit); 877 readback(regs->asc_cmd); 878 regs->asc_cmd = ASC_CMD_DMA; 879 readback(regs->asc_cmd); 880 881 regs->asc_dbus_id = target; 882 readback(regs->asc_dbus_id); 883 regs->asc_syn_p = state->sync_period; 884 readback(regs->asc_syn_p); 885 regs->asc_syn_o = state->sync_offset; 886 readback(regs->asc_syn_o); 887 888 /*XXX PEFO */ 889 /* we are not using sync transfer now, need to check this if we will */ 890 891 if (state->flags & TRY_SYNC) 892 regs->asc_cmd = ASC_CMD_SEL_ATN_STOP; 893 else 894 regs->asc_cmd = ASC_CMD_SEL_ATN; 895 readback(regs->asc_cmd); 896 } 897 898 /* 899 * Interrupt routine 900 * Take interrupts from the chip 901 * 902 * Implementation: 903 * Move along the current command's script if 904 * all is well, invoke error handler if not. 905 */ 906 int 907 asc_intr(sc) 908 void *sc; 909 { 910 asc_softc_t asc = sc; 911 asc_regmap_t *regs = asc->regs; 912 State *state; 913 script_t *scpt; 914 int ss, ir, status; 915 916 /* collect ephemeral information */ 917 status = regs->asc_status; 918 ss = regs->asc_ss; 919 920 if ((status & ASC_CSR_INT) == 0) /* Make shure it's a real interrupt */ 921 return(0); 922 923 ir = regs->asc_intr; /* this resets the previous two */ 924 scpt = asc->script; 925 926 #ifdef DEBUG 927 asc_logp->status = PACK(asc->sc_dev.dv_unit, status, ss, ir); 928 asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1; 929 asc_logp->state = scpt - asc_scripts; 930 asc_logp->msg = -1; 931 asc_logp->resid = 0; 932 if (++asc_logp >= &asc_log[NLOG]) 933 asc_logp = asc_log; 934 if (asc_debug > 2) 935 printf("asc_intr: status %x ss %x ir %x cond %d:%x\n", 936 status, ss, ir, scpt - asc_scripts, scpt->condition); 937 #endif 938 939 /* check the expected state */ 940 if (SCRIPT_MATCH(ir, status) == scpt->condition) { 941 /* 942 * Perform the appropriate operation, then proceed. 943 */ 944 if ((*scpt->action)(asc, status, ss, ir)) { 945 regs->asc_cmd = scpt->command; 946 readback(regs->asc_cmd); 947 asc->script = scpt->next; 948 } 949 goto done; 950 } 951 952 /* 953 * Check for parity error. 954 * Hardware will automatically set ATN 955 * to request the device for a MSG_OUT phase. 956 */ 957 if (status & ASC_CSR_PE) { 958 printf("%s: SCSI device %d: incomming parity error seen\n", 959 asc->sc_dev.dv_xname, asc->target); 960 asc->st[asc->target].flags |= PARITY_ERR; 961 } 962 963 /* 964 * Check for gross error. 965 * Probably a bug in a device driver. 966 */ 967 if (status & ASC_CSR_GE) { 968 printf("%s: SCSI device %d: gross error\n", 969 asc->sc_dev.dv_xname, asc->target); 970 goto abort; 971 } 972 973 /* check for message in or out */ 974 if ((ir & ~ASC_INT_FC) == ASC_INT_BS) { 975 register int len, fifo; 976 977 state = &asc->st[asc->target]; 978 switch (ASC_PHASE(status)) { 979 case ASC_PHASE_DATAI: 980 case ASC_PHASE_DATAO: 981 ASC_TC_GET(regs, len); 982 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 983 printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n", 984 state->buflen, state->dmalen, len, fifo); 985 goto abort; 986 987 case ASC_PHASE_MSG_IN: 988 break; 989 990 case ASC_PHASE_MSG_OUT: 991 /* 992 * Check for parity error. 993 * Hardware will automatically set ATN 994 * to request the device for a MSG_OUT phase. 995 */ 996 if (state->flags & PARITY_ERR) { 997 state->flags &= ~PARITY_ERR; 998 state->msg_out = SCSI_MESSAGE_PARITY_ERROR; 999 /* reset message in counter */ 1000 state->msglen = 0; 1001 } else 1002 state->msg_out = SCSI_NO_OP; 1003 regs->asc_fifo = state->msg_out; 1004 regs->asc_cmd = ASC_CMD_XFER_INFO; 1005 readback(regs->asc_cmd); 1006 goto done; 1007 1008 case ASC_PHASE_STATUS: 1009 /* probably an error in the SCSI command */ 1010 asc->script = &asc_scripts[SCRIPT_GET_STATUS]; 1011 regs->asc_cmd = ASC_CMD_I_COMPLETE; 1012 readback(regs->asc_cmd); 1013 goto done; 1014 1015 default: 1016 goto abort; 1017 } 1018 1019 if (state->script) 1020 goto abort; 1021 1022 /* 1023 * OK, message coming in clean up whatever is going on. 1024 * Get number of bytes left to transfered from byte counter 1025 * counter decrements when data is trf on the SCSI bus 1026 */ 1027 ASC_TC_GET(regs, len); 1028 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1029 /* flush any data in the FIFO */ 1030 if (fifo && !(state->flags & DMA_IN_PROGRESS)) { 1031 printf("asc_intr: fifo flush %d len %d fifo %x\n", fifo, len, regs->asc_fifo); 1032 regs->asc_cmd = ASC_CMD_FLUSH; 1033 readback(regs->asc_cmd); 1034 DELAY(2); 1035 } 1036 else if (fifo && state->flags & DMA_IN_PROGRESS) { 1037 if (state->flags & DMA_OUT) { 1038 len += fifo; /* Bytes dma'ed but not sent */ 1039 } 1040 else if (state->flags & DMA_IN) { 1041 printf("asc_intr: IN: dmalen %d len %d fifo %d\n", 1042 state->dmalen, len, fifo); /* XXX */ 1043 } 1044 regs->asc_cmd = ASC_CMD_FLUSH; 1045 readback(regs->asc_cmd); 1046 DELAY(2); 1047 } 1048 if (len && (state->flags & DMA_IN_PROGRESS)) { 1049 /* save number of bytes still to be sent or received */ 1050 state->dmaresid = len; 1051 state->flags &= ~DMA_IN_PROGRESS; 1052 ASC_TC_PUT(regs, 0, asc->is24bit); 1053 #ifdef DEBUG 1054 if (asc_logp == asc_log) 1055 asc_log[NLOG - 1].resid = len; 1056 else 1057 asc_logp[-1].resid = len; 1058 #endif 1059 /* setup state to resume to */ 1060 if (state->flags & DMA_IN) { 1061 /* 1062 * Since the ASC_CNFG3_SRB bit of the 1063 * cnfg3 register bit is not set, 1064 * we just transferred an extra byte. 1065 * Since we can't resume on an odd byte 1066 * boundary, we copy the valid data out 1067 * and resume DMA at the start address. 1068 */ 1069 if (len & 1) { 1070 printf("asc_intr: msg in len %d (fifo %d)\n", 1071 len, fifo); /* XXX */ 1072 len = state->dmalen - len; 1073 goto do_in; 1074 } 1075 state->script = 1076 &asc_scripts[SCRIPT_RESUME_DMA_IN]; 1077 } else if (state->flags & DMA_OUT) 1078 state->script = 1079 &asc_scripts[SCRIPT_RESUME_DMA_OUT]; 1080 else 1081 state->script = asc->script; 1082 } else if (state->flags & DMA_IN) { 1083 if (len) { 1084 #ifdef DEBUG 1085 printf("asc_intr: 1: bn %d len %d (fifo %d)\n", 1086 asc_debug_bn, len, fifo); /* XXX */ 1087 #endif 1088 goto abort; 1089 } 1090 /* setup state to resume to */ 1091 if (state->flags & DMA_IN_PROGRESS) { 1092 len = state->dmalen; 1093 state->flags &= ~DMA_IN_PROGRESS; 1094 do_in: 1095 DMA_END(asc->dma); 1096 state->buf += len; 1097 state->buflen -= len; 1098 } 1099 if (state->buflen) 1100 state->script = 1101 &asc_scripts[SCRIPT_RESUME_IN]; 1102 else 1103 state->script = 1104 &asc_scripts[SCRIPT_RESUME_NO_DATA]; 1105 } else if (state->flags & DMA_OUT) { 1106 if (len) { 1107 printf("asc_intr: 2: len %d (fifo %d)\n", len, 1108 fifo); /* XXX */ 1109 /* XXX THEO */ 1110 #if 1 1111 regs->asc_cmd = ASC_CMD_FLUSH; 1112 readback(regs->asc_cmd); 1113 DELAY(2); 1114 len = 0; 1115 #else 1116 goto abort; 1117 #endif 1118 } 1119 /* 1120 * If this is the last chunk, the next expected 1121 * state is to get status. 1122 */ 1123 if (state->flags & DMA_IN_PROGRESS) { 1124 state->flags &= ~DMA_IN_PROGRESS; 1125 DMA_END(asc->dma); 1126 len = state->dmalen; 1127 state->buf += len; 1128 state->buflen -= len; 1129 } 1130 if (state->buflen) 1131 state->script = 1132 &asc_scripts[SCRIPT_RESUME_OUT]; 1133 else 1134 state->script = 1135 &asc_scripts[SCRIPT_RESUME_NO_DATA]; 1136 } else if (asc->script == &asc_scripts[SCRIPT_SIMPLE]) 1137 state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA]; 1138 else 1139 state->script = asc->script; 1140 1141 /* setup to receive a message */ 1142 asc->script = &asc_scripts[SCRIPT_MSG_IN]; 1143 state->msglen = 0; 1144 regs->asc_cmd = ASC_CMD_XFER_INFO; 1145 readback(regs->asc_cmd); 1146 goto done; 1147 } 1148 1149 /* check for SCSI bus reset */ 1150 if (ir & ASC_INT_RESET) { 1151 register int i; 1152 1153 printf("%s: SCSI bus reset!!\n", asc->sc_dev.dv_xname); 1154 /* need to flush any pending commands */ 1155 for (i = 0; i < ASC_NCMD; i++) { 1156 if (!asc->cmd[i]) 1157 continue; 1158 asc->cmd[i]->error = XS_DRIVER_STUFFUP; 1159 asc_end(asc, 0, 0, 0); 1160 } 1161 /* rearbitrate synchronous offset */ 1162 for (i = 0; i < ASC_NCMD; i++) { 1163 asc->st[i].sync_offset = 0; 1164 asc->st[i].flags = 0; 1165 } 1166 asc->target = -1; 1167 return(1); 1168 } 1169 1170 /* check for command errors */ 1171 if (ir & ASC_INT_ILL) 1172 goto abort; 1173 1174 /* check for disconnect */ 1175 if (ir & ASC_INT_DISC) { 1176 state = &asc->st[asc->target]; 1177 switch (asc->script - asc_scripts) { 1178 case SCRIPT_DONE: 1179 case SCRIPT_DISCONNECT: 1180 /* 1181 * Disconnects can happen normally when the 1182 * command is complete with the phase being 1183 * either ASC_PHASE_DATAO or ASC_PHASE_MSG_IN. 1184 * The SCRIPT_MATCH() only checks for one phase 1185 * so we can wind up here. 1186 * Perform the appropriate operation, then proceed. 1187 */ 1188 if ((*scpt->action)(asc, status, ss, ir)) { 1189 regs->asc_cmd = scpt->command; 1190 readback(regs->asc_cmd); 1191 asc->script = scpt->next; 1192 } 1193 goto done; 1194 1195 case SCRIPT_TRY_SYNC: 1196 case SCRIPT_SIMPLE: 1197 case SCRIPT_DATA_IN: 1198 case SCRIPT_DATA_OUT: /* one of the starting scripts */ 1199 if (ASC_SS(ss) == 0) { 1200 /* device did not respond */ 1201 if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) { 1202 regs->asc_cmd = ASC_CMD_FLUSH; 1203 readback(regs->asc_cmd); 1204 } 1205 asc->cmd[asc->target]->error = XS_SELTIMEOUT; 1206 asc_end(asc, status, ss, ir); 1207 return(1); 1208 } 1209 /* FALLTHROUGH */ 1210 1211 default: 1212 printf("%s: SCSI device %d: unexpected disconnect\n", 1213 asc->sc_dev.dv_xname, asc->target); 1214 #ifdef DEBUG 1215 asc_DumpLog("asc_disc"); 1216 #endif 1217 /* 1218 * On rare occasions my RZ24 does a disconnect during 1219 * data in phase and the following seems to keep it 1220 * happy. 1221 * XXX Should a scsi disk ever do this?? 1222 */ 1223 asc->script = &asc_scripts[SCRIPT_RESEL]; 1224 asc->state = ASC_STATE_RESEL; 1225 state->flags |= DISCONN; 1226 regs->asc_cmd = ASC_CMD_ENABLE_SEL; 1227 readback(regs->asc_cmd); 1228 return(1); 1229 } 1230 } 1231 1232 /* check for reselect */ 1233 if (ir & ASC_INT_RESEL) { 1234 unsigned fifo, id, msg; 1235 1236 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1237 if (fifo < 2) 1238 goto abort; 1239 /* read unencoded SCSI ID and convert to binary */ 1240 msg = regs->asc_fifo & asc->myidmask; 1241 for (id = 0; (msg & 1) == 0; id++) 1242 msg >>= 1; 1243 /* read identify message */ 1244 msg = regs->asc_fifo; 1245 #ifdef DEBUG 1246 if (asc_logp == asc_log) 1247 asc_log[NLOG - 1].msg = msg; 1248 else 1249 asc_logp[-1].msg = msg; 1250 #endif 1251 asc->state = ASC_STATE_BUSY; 1252 asc->target = id; 1253 state = &asc->st[id]; 1254 asc->script = state->script; 1255 state->script = (script_t *)0; 1256 if (!(state->flags & DISCONN)) 1257 goto abort; 1258 state->flags &= ~DISCONN; 1259 regs->asc_syn_p = state->sync_period; 1260 regs->asc_syn_o = state->sync_offset; 1261 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1262 readback(regs->asc_cmd); 1263 goto done; 1264 } 1265 1266 /* check if we are being selected as a target */ 1267 if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN)) 1268 goto abort; 1269 1270 /* 1271 * 'ir' must be just ASC_INT_FC. 1272 * This is normal if canceling an ASC_ENABLE_SEL. 1273 */ 1274 1275 done: 1276 wbflush(); 1277 /* 1278 * If the next interrupt comes in immediatly the interrupt 1279 * dispatcher (which we are returning to) will catch it 1280 * before returning to the interrupted code. 1281 */ 1282 return(1); 1283 1284 abort: 1285 #ifdef DEBUG 1286 asc_DumpLog("asc_intr"); 1287 #endif 1288 panic("asc_intr"); 1289 return(1); 1290 } 1291 1292 /* 1293 * All the many little things that the interrupt 1294 * routine might switch to. 1295 */ 1296 1297 /* ARGSUSED */ 1298 static int 1299 script_nop(asc, status, ss, ir) 1300 asc_softc_t asc; 1301 int status, ss, ir; 1302 { 1303 return (1); 1304 } 1305 1306 /* ARGSUSED */ 1307 static int 1308 asc_get_status(asc, status, ss, ir) 1309 register asc_softc_t asc; 1310 register int status, ss, ir; 1311 { 1312 register asc_regmap_t *regs = asc->regs; 1313 register int data; 1314 1315 /* 1316 * Get the last two bytes in the FIFO. 1317 */ 1318 if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) { 1319 printf("asc_get_status: cmdreg %x, fifo cnt %d\n", 1320 regs->asc_cmd, data); /* XXX */ 1321 #ifdef DEBUG 1322 asc_DumpLog("get_status"); /* XXX */ 1323 #endif 1324 if (data < 2) { 1325 asc->regs->asc_cmd = ASC_CMD_MSG_ACPT; 1326 readback(asc->regs->asc_cmd); 1327 return (0); 1328 } 1329 do { 1330 data = regs->asc_fifo; 1331 } while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2); 1332 } 1333 1334 /* save the status byte */ 1335 asc->st[asc->target].statusByte = data = regs->asc_fifo; 1336 #ifdef DEBUG 1337 if (asc_logp == asc_log) 1338 asc_log[NLOG - 1].msg = data; 1339 else 1340 asc_logp[-1].msg = data; 1341 #endif 1342 1343 /* get the (presumed) command_complete message */ 1344 if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE) 1345 return (1); 1346 1347 #ifdef DEBUG 1348 printf("asc_get_status: status %x cmd %x\n", 1349 asc->st[asc->target].statusByte, data); 1350 asc_DumpLog("asc_get_status"); 1351 #endif 1352 return (0); 1353 } 1354 1355 /* ARGSUSED */ 1356 static int 1357 asc_end(asc, status, ss, ir) 1358 asc_softc_t asc; 1359 int status, ss, ir; 1360 { 1361 struct scsipi_xfer *scsicmd; 1362 struct scsipi_periph *periph; 1363 State *state; 1364 int i, target; 1365 1366 asc->state = ASC_STATE_IDLE; 1367 target = asc->target; 1368 asc->target = -1; 1369 scsicmd = asc->cmd[target]; 1370 periph = scsicmd->xs_periph; 1371 asc->cmd[target] = (struct scsipi_xfer *)0; 1372 state = &asc->st[target]; 1373 1374 #ifdef DEBUG 1375 if (asc_debug > 1) { 1376 printf("asc_end: %s target %d cmd %x err %d resid %d\n", 1377 asc->sc_dev.dv_xname, target, 1378 state->cmd.opcode, scsicmd->error, state->buflen); 1379 } 1380 #endif 1381 #ifdef DIAGNOSTIC 1382 if (target < 0 || !scsicmd) 1383 panic("asc_end"); 1384 #endif 1385 1386 /* look for disconnected devices */ 1387 for (i = 0; i < ASC_NCMD; i++) { 1388 if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN)) 1389 continue; 1390 asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL; 1391 readback(asc->regs->asc_cmd); 1392 asc->state = ASC_STATE_RESEL; 1393 asc->script = &asc_scripts[SCRIPT_RESEL]; 1394 break; 1395 } 1396 1397 if(scsicmd->error == XS_NOERROR) { 1398 if((state->statusByte & ST_MASK) == SCSI_CHECK) { 1399 scsicmd->status = state->statusByte; 1400 scsicmd->error = XS_BUSY; 1401 } 1402 } 1403 1404 scsicmd->resid = state->buflen; 1405 1406 /* 1407 * Look for another device that is ready. 1408 * May want to keep last one started and increment for fairness 1409 * rather than always starting at zero. 1410 */ 1411 for (i = 0; i < ASC_NCMD; i++) { 1412 /* don't restart a disconnected command */ 1413 if (!asc->cmd[i] || (asc->st[i].flags & DISCONN)) 1414 continue; 1415 asc_startcmd(asc, i); 1416 break; 1417 } 1418 1419 /* signal device driver that the command is done */ 1420 scsipi_done(scsicmd); 1421 1422 return (0); 1423 } 1424 1425 /* ARGSUSED */ 1426 static int 1427 asc_dma_in(asc, status, ss, ir) 1428 register asc_softc_t asc; 1429 register int status, ss, ir; 1430 { 1431 register asc_regmap_t *regs = asc->regs; 1432 register State *state = &asc->st[asc->target]; 1433 register int len; 1434 1435 /* check for previous chunk in buffer */ 1436 if (state->flags & DMA_IN_PROGRESS) { 1437 /* 1438 * Only count bytes that have been copied to memory. 1439 * There may be some bytes in the FIFO if synchonous transfers 1440 * are in progress. 1441 */ 1442 DMA_END(asc->dma); 1443 ASC_TC_GET(regs, len); 1444 len = state->dmalen - len; 1445 state->buf += len; 1446 state->buflen -= len; 1447 } 1448 1449 /* setup to start reading the next chunk */ 1450 len = state->buflen; 1451 #ifdef DEBUG 1452 if (asc_logp == asc_log) 1453 asc_log[NLOG - 1].resid = len; 1454 else 1455 asc_logp[-1].resid = len; 1456 #endif 1457 if (len > state->dmaBufSize) 1458 len = state->dmaBufSize; 1459 state->dmalen = len; 1460 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV); 1461 ASC_TC_PUT(regs, len, asc->is24bit); 1462 #ifdef DEBUG 1463 if (asc_debug > 2) 1464 printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len); 1465 #endif 1466 1467 /* check for next chunk */ 1468 state->flags |= DMA_IN_PROGRESS; 1469 if (len != state->buflen) { 1470 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1471 readback(regs->asc_cmd); 1472 asc->script = &asc_scripts[SCRIPT_CONTINUE_IN]; 1473 return (0); 1474 } 1475 return (1); 1476 } 1477 1478 /* ARGSUSED */ 1479 static int 1480 asc_last_dma_in(asc, status, ss, ir) 1481 register asc_softc_t asc; 1482 register int status, ss, ir; 1483 { 1484 register asc_regmap_t *regs = asc->regs; 1485 register State *state = &asc->st[asc->target]; 1486 register int len, fifo; 1487 1488 DMA_END(asc->dma); 1489 ASC_TC_GET(regs, len); 1490 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1491 #ifdef DEBUG 1492 if (asc_debug > 2) 1493 printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n", 1494 state->buflen, state->dmalen, len, fifo); 1495 #endif 1496 if (fifo) { 1497 /* device must be trying to send more than we expect */ 1498 regs->asc_cmd = ASC_CMD_FLUSH; 1499 readback(regs->asc_cmd); 1500 } 1501 state->flags &= ~DMA_IN_PROGRESS; 1502 len = state->dmalen - len; 1503 state->buflen -= len; 1504 1505 return (1); 1506 } 1507 1508 /* ARGSUSED */ 1509 static int 1510 asc_resume_in(asc, status, ss, ir) 1511 register asc_softc_t asc; 1512 register int status, ss, ir; 1513 { 1514 register asc_regmap_t *regs = asc->regs; 1515 register State *state = &asc->st[asc->target]; 1516 register int len; 1517 1518 /* setup to start reading the next chunk */ 1519 len = state->buflen; 1520 #ifdef DEBUG 1521 if (asc_logp == asc_log) 1522 asc_log[NLOG - 1].resid = len; 1523 else 1524 asc_logp[-1].resid = len; 1525 #endif 1526 if (len > state->dmaBufSize) 1527 len = state->dmaBufSize; 1528 state->dmalen = len; 1529 #ifdef DEBUG 1530 if (asc_logp == asc_log) 1531 asc_log[NLOG - 1].resid = len; 1532 else 1533 asc_logp[-1].resid = len; 1534 #endif 1535 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV); 1536 ASC_TC_PUT(regs, len, asc->is24bit); 1537 #ifdef DEBUG 1538 if (asc_debug > 2) 1539 printf("asc_resume_in: buflen %d, len %d\n", state->buflen, 1540 len); 1541 #endif 1542 1543 /* check for next chunk */ 1544 state->flags |= DMA_IN_PROGRESS; 1545 if (len != state->buflen) { 1546 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1547 readback(regs->asc_cmd); 1548 asc->script = &asc_scripts[SCRIPT_CONTINUE_IN]; 1549 return (0); 1550 } 1551 return (1); 1552 } 1553 1554 /* ARGSUSED */ 1555 static int 1556 asc_resume_dma_in(asc, status, ss, ir) 1557 register asc_softc_t asc; 1558 register int status, ss, ir; 1559 { 1560 register asc_regmap_t *regs = asc->regs; 1561 register State *state = &asc->st[asc->target]; 1562 register int len, off; 1563 1564 /* setup to finish reading the current chunk */ 1565 len = state->dmaresid; 1566 off = state->dmalen - len; 1567 if ((off & 1) && state->sync_offset) { 1568 printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n", 1569 state->dmalen, len, off); /* XXX */ 1570 regs->asc_res_fifo = ((u_char *)state->buf)[off]; 1571 /*XXX Need to flush cache ? */ 1572 } 1573 DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_FROM_DEV); 1574 ASC_TC_PUT(regs, len, asc->is24bit); 1575 #ifdef DEBUG 1576 if (asc_debug > 2) 1577 printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n", 1578 state->dmalen, state->buflen, len, off); 1579 #endif 1580 1581 /* check for next chunk */ 1582 state->flags |= DMA_IN_PROGRESS; 1583 if (state->dmalen != state->buflen) { 1584 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1585 readback(regs->asc_cmd); 1586 asc->script = &asc_scripts[SCRIPT_CONTINUE_IN]; 1587 return (0); 1588 } 1589 return (1); 1590 } 1591 1592 /* ARGSUSED */ 1593 static int 1594 asc_dma_out(asc, status, ss, ir) 1595 register asc_softc_t asc; 1596 register int status, ss, ir; 1597 { 1598 register asc_regmap_t *regs = asc->regs; 1599 register State *state = &asc->st[asc->target]; 1600 register int len, fifo; 1601 1602 if (state->flags & DMA_IN_PROGRESS) { 1603 /* check to be sure previous chunk was finished */ 1604 ASC_TC_GET(regs, len); 1605 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1606 if (len || fifo) 1607 printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n", 1608 state->buflen, state->dmalen, len, fifo); /* XXX */ 1609 len += fifo; 1610 len = state->dmalen - len; 1611 state->buf += len; 1612 state->buflen -= len; 1613 } 1614 1615 /* setup for this chunk */ 1616 len = state->buflen; 1617 #ifdef DEBUG 1618 if (asc_logp == asc_log) 1619 asc_log[NLOG - 1].resid = len; 1620 else 1621 asc_logp[-1].resid = len; 1622 #endif 1623 if (len > state->dmaBufSize) 1624 len = state->dmaBufSize; 1625 state->dmalen = len; 1626 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV); 1627 ASC_TC_PUT(regs, len, asc->is24bit); 1628 #ifdef DEBUG 1629 if (asc_debug > 2) 1630 printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len); 1631 #endif 1632 1633 /* check for next chunk */ 1634 state->flags |= DMA_IN_PROGRESS; 1635 if (len != state->buflen) { 1636 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1637 readback(regs->asc_cmd); 1638 asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT]; 1639 return (0); 1640 } 1641 return (1); 1642 } 1643 1644 /* ARGSUSED */ 1645 static int 1646 asc_last_dma_out(asc, status, ss, ir) 1647 register asc_softc_t asc; 1648 register int status, ss, ir; 1649 { 1650 register asc_regmap_t *regs = asc->regs; 1651 register State *state = &asc->st[asc->target]; 1652 register int len, fifo; 1653 1654 ASC_TC_GET(regs, len); 1655 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 1656 #ifdef DEBUG 1657 if (asc_debug > 2) 1658 printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n", 1659 state->buflen, state->dmalen, len, fifo); 1660 #endif 1661 if (fifo) { 1662 len += fifo; 1663 regs->asc_cmd = ASC_CMD_FLUSH; 1664 readback(regs->asc_cmd); 1665 } 1666 state->flags &= ~DMA_IN_PROGRESS; 1667 len = state->dmalen - len; 1668 state->buflen -= len; 1669 return (1); 1670 } 1671 1672 /* ARGSUSED */ 1673 static int 1674 asc_resume_out(asc, status, ss, ir) 1675 register asc_softc_t asc; 1676 register int status, ss, ir; 1677 { 1678 register asc_regmap_t *regs = asc->regs; 1679 register State *state = &asc->st[asc->target]; 1680 register int len; 1681 1682 /* setup for this chunk */ 1683 len = state->buflen; 1684 #ifdef DEBUG 1685 if (asc_logp == asc_log) 1686 asc_log[NLOG - 1].resid = len; 1687 else 1688 asc_logp[-1].resid = len; 1689 #endif 1690 if (len > state->dmaBufSize) 1691 len = state->dmaBufSize; 1692 state->dmalen = len; 1693 #ifdef DEBUG 1694 if (asc_logp == asc_log) 1695 asc_log[NLOG - 1].resid = len; 1696 else 1697 asc_logp[-1].resid = len; 1698 #endif 1699 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV); 1700 ASC_TC_PUT(regs, len, asc->is24bit); 1701 #ifdef DEBUG 1702 if (asc_debug > 2) 1703 printf("asc_resume_out: buflen %d, len %d\n", state->buflen, 1704 len); 1705 #endif 1706 1707 /* check for next chunk */ 1708 state->flags |= DMA_IN_PROGRESS; 1709 if (len != state->buflen) { 1710 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1711 readback(regs->asc_cmd); 1712 asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT]; 1713 return (0); 1714 } 1715 return (1); 1716 } 1717 1718 /* ARGSUSED */ 1719 static int 1720 asc_resume_dma_out(asc, status, ss, ir) 1721 register asc_softc_t asc; 1722 register int status, ss, ir; 1723 { 1724 register asc_regmap_t *regs = asc->regs; 1725 register State *state = &asc->st[asc->target]; 1726 register int len, off; 1727 1728 /* setup to finish writing this chunk */ 1729 len = state->dmaresid; 1730 off = state->dmalen - len; 1731 if (off & 1) { 1732 printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n", 1733 state->dmalen, len, off); /* XXX */ 1734 regs->asc_fifo = ((u_char *)state->buf)[off]; 1735 /*XXX Need to flush Cache ? */ 1736 off++; 1737 len--; 1738 } 1739 DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_TO_DEV); 1740 ASC_TC_PUT(regs, len, asc->is24bit); 1741 #ifdef DEBUG 1742 if (asc_debug > 2) 1743 printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n", 1744 state->dmalen, state->buflen, len, off); 1745 #endif 1746 1747 /* check for next chunk */ 1748 state->flags |= DMA_IN_PROGRESS; 1749 if (state->dmalen != state->buflen) { 1750 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 1751 readback(regs->asc_cmd); 1752 asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT]; 1753 return (0); 1754 } 1755 return (1); 1756 } 1757 1758 /* ARGSUSED */ 1759 static int 1760 asc_sendsync(asc, status, ss, ir) 1761 register asc_softc_t asc; 1762 register int status, ss, ir; 1763 { 1764 register asc_regmap_t *regs = asc->regs; 1765 register State *state = &asc->st[asc->target]; 1766 1767 /* send the extended synchronous negotiation message */ 1768 regs->asc_fifo = SCSI_EXTENDED_MSG; 1769 wbflush(); 1770 regs->asc_fifo = 3; 1771 wbflush(); 1772 regs->asc_fifo = SCSI_SYNCHRONOUS_XFER; 1773 wbflush(); 1774 regs->asc_fifo = SCSI_MIN_PERIOD; 1775 wbflush(); 1776 regs->asc_fifo = ASC_MAX_OFFSET; 1777 /* state to resume after we see the sync reply message */ 1778 state->script = asc->script + 2; 1779 state->msglen = 0; 1780 return (1); 1781 } 1782 1783 /* ARGSUSED */ 1784 static int 1785 asc_replysync(asc, status, ss, ir) 1786 register asc_softc_t asc; 1787 register int status, ss, ir; 1788 { 1789 register asc_regmap_t *regs = asc->regs; 1790 register State *state = &asc->st[asc->target]; 1791 1792 #ifdef DEBUG 1793 if (asc_debug > 2) 1794 printf("asc_replysync: %x %x\n", 1795 asc_to_scsi_period[state->sync_period] * asc->tb_ticks, 1796 state->sync_offset); 1797 #endif 1798 /* send synchronous transfer in response to a request */ 1799 regs->asc_fifo = SCSI_EXTENDED_MSG; 1800 wbflush(); 1801 regs->asc_fifo = 3; 1802 wbflush(); 1803 regs->asc_fifo = SCSI_SYNCHRONOUS_XFER; 1804 wbflush(); 1805 regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks; 1806 wbflush(); 1807 regs->asc_fifo = state->sync_offset; 1808 regs->asc_cmd = ASC_CMD_XFER_INFO; 1809 readback(regs->asc_cmd); 1810 1811 /* return to the appropriate script */ 1812 if (!state->script) { 1813 #ifdef DEBUG 1814 asc_DumpLog("asc_replsync"); 1815 #endif 1816 panic("asc_replysync"); 1817 } 1818 asc->script = state->script; 1819 state->script = (script_t *)0; 1820 return (0); 1821 } 1822 1823 /* ARGSUSED */ 1824 static int 1825 asc_msg_in(asc, status, ss, ir) 1826 register asc_softc_t asc; 1827 register int status, ss, ir; 1828 { 1829 register asc_regmap_t *regs = asc->regs; 1830 register State *state = &asc->st[asc->target]; 1831 register int msg; 1832 int i; 1833 1834 /* read one message byte */ 1835 msg = regs->asc_fifo; 1836 #ifdef DEBUG 1837 if (asc_logp == asc_log) 1838 asc_log[NLOG - 1].msg = msg; 1839 else 1840 asc_logp[-1].msg = msg; 1841 #endif 1842 1843 /* check for multi-byte message */ 1844 if (state->msglen != 0) { 1845 /* first byte is the message length */ 1846 if (state->msglen < 0) { 1847 state->msglen = msg; 1848 return (1); 1849 } 1850 if (state->msgcnt >= state->msglen) 1851 goto abort; 1852 state->msg_in[state->msgcnt++] = msg; 1853 1854 /* did we just read the last byte of the message? */ 1855 if (state->msgcnt != state->msglen) 1856 return (1); 1857 1858 /* process an extended message */ 1859 #ifdef DEBUG 1860 if (asc_debug > 2) 1861 printf("asc_msg_in: msg %x %x %x\n", 1862 state->msg_in[0], 1863 state->msg_in[1], 1864 state->msg_in[2]); 1865 #endif 1866 switch (state->msg_in[0]) { 1867 case SCSI_SYNCHRONOUS_XFER: 1868 state->flags |= DID_SYNC; 1869 state->sync_offset = state->msg_in[2]; 1870 1871 /* convert SCSI period to ASC period */ 1872 i = state->msg_in[1] / asc->tb_ticks; 1873 if (i < asc->min_period) 1874 i = asc->min_period; 1875 else if (i >= asc->max_period) { 1876 /* can't do sync transfer, period too long */ 1877 printf("%s: SCSI device %d: sync xfer period too long (%d)\n", 1878 asc->sc_dev.dv_xname, asc->target, i); 1879 i = asc->max_period; 1880 state->sync_offset = 0; 1881 } 1882 if ((i * asc->tb_ticks) != state->msg_in[1]) 1883 i++; 1884 state->sync_period = i & 0x1F; 1885 1886 /* 1887 * If this is a request, check minimums and 1888 * send back an acknowledge. 1889 */ 1890 if (!(state->flags & TRY_SYNC)) { 1891 regs->asc_cmd = ASC_CMD_SET_ATN; 1892 readback(regs->asc_cmd); 1893 1894 if (state->sync_period < asc->min_period) 1895 state->sync_period = 1896 asc->min_period; 1897 if (state->sync_offset > ASC_MAX_OFFSET) 1898 state->sync_offset = 1899 ASC_MAX_OFFSET; 1900 asc->script = &asc_scripts[SCRIPT_REPLY_SYNC]; 1901 regs->asc_syn_p = state->sync_period; 1902 readback(regs->asc_syn_p); 1903 regs->asc_syn_o = state->sync_offset; 1904 readback(regs->asc_syn_o); 1905 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1906 readback(regs->asc_cmd); 1907 return (0); 1908 } 1909 1910 regs->asc_syn_p = state->sync_period; 1911 readback(regs->asc_syn_p); 1912 regs->asc_syn_o = state->sync_offset; 1913 readback(regs->asc_syn_o); 1914 goto done; 1915 1916 default: 1917 printf("%s: SCSI device %d: rejecting extended message 0x%x\n", 1918 asc->sc_dev.dv_xname, asc->target, 1919 state->msg_in[0]); 1920 goto reject; 1921 } 1922 } 1923 1924 /* process first byte of a message */ 1925 #ifdef DEBUG 1926 if (asc_debug > 2) 1927 printf("asc_msg_in: msg %x\n", msg); 1928 #endif 1929 switch (msg) { 1930 #if 0 1931 case SCSI_MESSAGE_REJECT: 1932 printf(" did not like SYNCH xfer "); /* XXX */ 1933 state->flags |= DID_SYNC; 1934 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1935 readback(regs->asc_cmd); 1936 status = asc_wait(regs, ASC_CSR_INT); 1937 ir = regs->asc_intr; 1938 /* some just break out here, some dont */ 1939 if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) { 1940 regs->asc_fifo = SCSI_ABORT; 1941 regs->asc_cmd = ASC_CMD_XFER_INFO; 1942 readback(regs->asc_cmd); 1943 status = asc_wait(regs, ASC_CSR_INT); 1944 ir = regs->asc_intr; 1945 } 1946 if (ir & ASC_INT_DISC) { 1947 asc_end(asc, status, 0, ir); 1948 return (0); 1949 } 1950 goto status; 1951 #endif /* 0 */ 1952 1953 case SCSI_EXTENDED_MSG: /* read an extended message */ 1954 /* setup to read message length next */ 1955 state->msglen = -1; 1956 state->msgcnt = 0; 1957 return (1); 1958 1959 case SCSI_NO_OP: 1960 break; 1961 1962 case SCSI_SAVE_DATA_POINTER: 1963 /* expect another message */ 1964 return (1); 1965 1966 case SCSI_RESTORE_POINTERS: 1967 /* 1968 * Need to do the following if resuming synchonous data in 1969 * on an odd byte boundary. 1970 regs->asc_cnfg2 |= ASC_CNFG2_RFB; 1971 */ 1972 break; 1973 1974 case SCSI_DISCONNECT: 1975 if (state->flags & DISCONN) 1976 goto abort; 1977 state->flags |= DISCONN; 1978 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1979 readback(regs->asc_cmd); 1980 asc->script = &asc_scripts[SCRIPT_DISCONNECT]; 1981 return (0); 1982 1983 default: 1984 printf("%s: SCSI device %d: rejecting message 0x%x\n", 1985 asc->sc_dev.dv_xname, asc->target, msg); 1986 reject: 1987 /* request a message out before acknowledging this message */ 1988 state->msg_out = SCSI_MESSAGE_REJECT; 1989 regs->asc_cmd = ASC_CMD_SET_ATN; 1990 readback(regs->asc_cmd); 1991 } 1992 1993 done: 1994 /* return to original script */ 1995 regs->asc_cmd = ASC_CMD_MSG_ACPT; 1996 readback(regs->asc_cmd); 1997 if (!state->script) { 1998 abort: 1999 #ifdef DEBUG 2000 asc_DumpLog("asc_msg_in"); 2001 #endif 2002 panic("asc_msg_in"); 2003 } 2004 asc->script = state->script; 2005 state->script = (script_t *)0; 2006 return (0); 2007 } 2008 2009 /* ARGSUSED */ 2010 static int 2011 asc_disconnect(asc, status, ss, ir) 2012 asc_softc_t asc; 2013 int status, ss, ir; 2014 { 2015 #ifdef DIAGNOSTIC 2016 if (!(asc->st[asc->target].flags & DISCONN)) { 2017 printf("asc_disconnect: device %d: DISCONN not set!\n", 2018 asc->target); 2019 } 2020 #endif /* DIAGNOSTIC */ 2021 asc->target = -1; 2022 asc->state = ASC_STATE_RESEL; 2023 return (1); 2024 } 2025 2026 #ifdef DEBUG 2027 /* 2028 * Dump the log buffer. 2029 */ 2030 static void 2031 asc_DumpLog(str) 2032 char *str; 2033 { 2034 register struct asc_log *lp; 2035 register u_int status; 2036 2037 printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd, 2038 asc_debug_bn, asc_debug_sz); 2039 lp = asc_logp; 2040 do { 2041 status = lp->status; 2042 printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n", 2043 status >> 24, 2044 lp->target, 2045 (status >> 16) & 0xFF, 2046 (status >> 8) & 0xFF, 2047 status & 0XFF, 2048 lp->state, 2049 asc_scripts[lp->state].condition, 2050 lp->msg, lp->resid); 2051 if (++lp >= &asc_log[NLOG]) 2052 lp = asc_log; 2053 } while (lp != asc_logp); 2054 } 2055 #endif /* DEBUG */ 2056