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