152889Sbostic /*- 263205Sbostic * Copyright (c) 1992, 1993 363205Sbostic * The Regents of the University of California. All rights reserved. 452889Sbostic * 552889Sbostic * This code is derived from software contributed to Berkeley by 656819Sralph * Ralph Campbell and Rick Macklem. 752889Sbostic * 852889Sbostic * %sccs.include.redist.c% 952889Sbostic * 10*67476Smckusick * @(#)asc.c 8.3 (Berkeley) 07/03/94 1152889Sbostic */ 1252889Sbostic 1352889Sbostic /* 1452889Sbostic * Mach Operating System 1552889Sbostic * Copyright (c) 1991,1990,1989 Carnegie Mellon University 1652889Sbostic * All Rights Reserved. 1752889Sbostic * 1852889Sbostic * Permission to use, copy, modify and distribute this software and its 1952889Sbostic * documentation is hereby granted, provided that both the copyright 2052889Sbostic * notice and this permission notice appear in all copies of the 2152889Sbostic * software, derivative works or modified versions, and any portions 2252889Sbostic * thereof, and that both notices appear in supporting documentation. 2352889Sbostic * 2452889Sbostic * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 2552889Sbostic * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 2652889Sbostic * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 2752889Sbostic * 2852889Sbostic * Carnegie Mellon requests users of this software to return to 2952889Sbostic * 3052889Sbostic * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 3152889Sbostic * School of Computer Science 3252889Sbostic * Carnegie Mellon University 3352889Sbostic * Pittsburgh PA 15213-3890 3452889Sbostic * 3552889Sbostic * any improvements or extensions that they make and grant Carnegie the 3652889Sbostic * rights to redistribute these changes. 3752889Sbostic */ 3852889Sbostic 3952889Sbostic /* 4052889Sbostic * HISTORY 4152889Sbostic * $Log: scsi_53C94_hdw.c,v $ 4252889Sbostic * Revision 2.5 91/02/05 17:45:07 mrt 4352889Sbostic * Added author notices 4452889Sbostic * [91/02/04 11:18:43 mrt] 4552889Sbostic * 4652889Sbostic * Changed to use new Mach copyright 4752889Sbostic * [91/02/02 12:17:20 mrt] 4852889Sbostic * 4952889Sbostic * Revision 2.4 91/01/08 15:48:24 rpd 5052889Sbostic * Added continuation argument to thread_block. 5152889Sbostic * [90/12/27 rpd] 5252889Sbostic * 5352889Sbostic * Revision 2.3 90/12/05 23:34:48 af 5452889Sbostic * Recovered from pmax merge.. and from the destruction of a disk. 5552889Sbostic * [90/12/03 23:40:40 af] 5652889Sbostic * 5752889Sbostic * Revision 2.1.1.1 90/11/01 03:39:09 af 5852889Sbostic * Created, from the DEC specs: 5952889Sbostic * "PMAZ-AA TURBOchannel SCSI Module Functional Specification" 6052889Sbostic * Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990. 6152889Sbostic * And from the NCR data sheets 6252889Sbostic * "NCR 53C94, 53C95, 53C96 Advances SCSI Controller" 6352889Sbostic * [90/09/03 af] 6452889Sbostic */ 6552889Sbostic 6652889Sbostic /* 6752889Sbostic * File: scsi_53C94_hdw.h 6852889Sbostic * Author: Alessandro Forin, Carnegie Mellon University 6952889Sbostic * Date: 9/90 7052889Sbostic * 7152889Sbostic * Bottom layer of the SCSI driver: chip-dependent functions 7252889Sbostic * 7352889Sbostic * This file contains the code that is specific to the NCR 53C94 7452889Sbostic * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start 7552889Sbostic * operation, and interrupt routine. 7652889Sbostic */ 7752889Sbostic 7852889Sbostic /* 7952889Sbostic * This layer works based on small simple 'scripts' that are installed 8052889Sbostic * at the start of the command and drive the chip to completion. 8152889Sbostic * The idea comes from the specs of the NCR 53C700 'script' processor. 8252889Sbostic * 8352889Sbostic * There are various reasons for this, mainly 8452889Sbostic * - Performance: identify the common (successful) path, and follow it; 8552889Sbostic * at interrupt time no code is needed to find the current status 8652889Sbostic * - Code size: it should be easy to compact common operations 8752889Sbostic * - Adaptability: the code skeleton should adapt to different chips without 8852889Sbostic * terrible complications. 8952889Sbostic * - Error handling: and it is easy to modify the actions performed 9052889Sbostic * by the scripts to cope with strange but well identified sequences 9152889Sbostic * 9252889Sbostic */ 9352889Sbostic 9456819Sralph #include <asc.h> 9552889Sbostic #if NASC > 0 9652889Sbostic 9756522Sbostic #include <sys/param.h> 9856522Sbostic #include <sys/systm.h> 9956819Sralph #include <sys/dkstat.h> 10056819Sralph #include <sys/buf.h> 10156819Sralph #include <sys/conf.h> 10256522Sbostic #include <sys/errno.h> 10352889Sbostic 10456819Sralph #include <machine/machConst.h> 10556819Sralph 10656525Sbostic #include <pmax/dev/device.h> 10756525Sbostic #include <pmax/dev/scsi.h> 10856525Sbostic #include <pmax/dev/ascreg.h> 10952889Sbostic 11056819Sralph #include <pmax/pmax/asic.h> 11156819Sralph #include <pmax/pmax/kmin.h> 11256819Sralph #include <pmax/pmax/pmaxtype.h> 11356819Sralph 11456819Sralph #define readback(a) { register int foo; foo = (a); } 11556819Sralph extern int pmax_boardtype; 11656819Sralph 11756819Sralph /* 11856819Sralph * In 4ns ticks. 11956819Sralph */ 12052889Sbostic int asc_to_scsi_period[] = { 12156819Sralph 32, 12256819Sralph 33, 12356819Sralph 34, 12456819Sralph 35, 12556819Sralph 5, 12656819Sralph 5, 12756819Sralph 6, 12856819Sralph 7, 12956819Sralph 8, 13056819Sralph 9, 13156819Sralph 10, 13256819Sralph 11, 13356819Sralph 12, 13456819Sralph 13, 13556819Sralph 14, 13656819Sralph 15, 13756819Sralph 16, 13856819Sralph 17, 13956819Sralph 18, 14056819Sralph 19, 14156819Sralph 20, 14256819Sralph 21, 14356819Sralph 22, 14456819Sralph 23, 14556819Sralph 24, 14656819Sralph 25, 14756819Sralph 26, 14856819Sralph 27, 14956819Sralph 28, 15056819Sralph 29, 15156819Sralph 30, 15256819Sralph 31, 15352889Sbostic }; 15452889Sbostic 15552889Sbostic /* 15652889Sbostic * Internal forward declarations. 15752889Sbostic */ 15852889Sbostic static void asc_reset(); 15952889Sbostic static void asc_startcmd(); 16052889Sbostic 16152889Sbostic #ifdef DEBUG 16252889Sbostic int asc_debug = 1; 16352889Sbostic int asc_debug_cmd; 16452889Sbostic int asc_debug_bn; 16552889Sbostic int asc_debug_sz; 16658658Sralph #define NLOG 32 16752889Sbostic struct asc_log { 16852889Sbostic u_int status; 16952889Sbostic u_char state; 17052889Sbostic u_char msg; 17152889Sbostic int target; 17258658Sralph int resid; 17352889Sbostic } asc_log[NLOG], *asc_logp = asc_log; 17452889Sbostic #define PACK(unit, status, ss, ir) \ 17552889Sbostic ((unit << 24) | (status << 16) | (ss << 8) | ir) 17652889Sbostic #endif 17752889Sbostic 17852889Sbostic /* 17952889Sbostic * Scripts are entries in a state machine table. 18052889Sbostic * A script has four parts: a pre-condition, an action, a command to the chip, 18152889Sbostic * and an index into asc_scripts for the next state. The first triggers error 18252889Sbostic * handling if not satisfied and in our case it is formed by the 18352889Sbostic * values of the interrupt register and status register, this 18452889Sbostic * basically captures the phase of the bus and the TC and BS 18552889Sbostic * bits. The action part is just a function pointer, and the 18652889Sbostic * command is what the 53C94 should be told to do at the end 18752889Sbostic * of the action processing. This command is only issued and the 18852889Sbostic * script proceeds if the action routine returns TRUE. 18952889Sbostic * See asc_intr() for how and where this is all done. 19052889Sbostic */ 19152889Sbostic typedef struct script { 19252889Sbostic int condition; /* expected state at interrupt time */ 19352889Sbostic int (*action)(); /* extra operations */ 19452889Sbostic int command; /* command to the chip */ 19552889Sbostic struct script *next; /* index into asc_scripts for next state */ 19652889Sbostic } script_t; 19752889Sbostic 19852889Sbostic /* Matching on the condition value */ 19958658Sralph #define SCRIPT_MATCH(ir, csr) ((ir) | (((csr) & 0x67) << 8)) 20052889Sbostic 20152889Sbostic /* forward decls of script actions */ 20256819Sralph static int script_nop(); /* when nothing needed */ 20356819Sralph static int asc_end(); /* all come to an end */ 20456819Sralph static int asc_get_status(); /* get status from target */ 20556819Sralph static int asc_dma_in(); /* start reading data from target */ 20656819Sralph static int asc_last_dma_in(); /* cleanup after all data is read */ 20756819Sralph static int asc_resume_in(); /* resume data in after a message */ 20856819Sralph static int asc_resume_dma_in(); /* resume DMA after a disconnect */ 20956819Sralph static int asc_dma_out(); /* send data to target via dma */ 21056819Sralph static int asc_last_dma_out(); /* cleanup after all data is written */ 21156819Sralph static int asc_resume_out(); /* resume data out after a message */ 21256819Sralph static int asc_resume_dma_out(); /* resume DMA after a disconnect */ 21356819Sralph static int asc_sendsync(); /* negotiate sync xfer */ 21456819Sralph static int asc_replysync(); /* negotiate sync xfer */ 21556819Sralph static int asc_msg_in(); /* process a message byte */ 21656819Sralph static int asc_disconnect(); /* process an expected disconnect */ 21752889Sbostic 21852889Sbostic /* Define the index into asc_scripts for various state transitions */ 21952889Sbostic #define SCRIPT_DATA_IN 0 22052942Sralph #define SCRIPT_CONTINUE_IN 2 22152942Sralph #define SCRIPT_DATA_OUT 3 22252942Sralph #define SCRIPT_CONTINUE_OUT 5 22352942Sralph #define SCRIPT_SIMPLE 6 22452942Sralph #define SCRIPT_GET_STATUS 7 22552942Sralph #define SCRIPT_MSG_IN 9 22652942Sralph #define SCRIPT_REPLY_SYNC 11 22752889Sbostic #define SCRIPT_TRY_SYNC 12 22852942Sralph #define SCRIPT_DISCONNECT 15 22952942Sralph #define SCRIPT_RESEL 16 23052942Sralph #define SCRIPT_RESUME_IN 17 23152942Sralph #define SCRIPT_RESUME_DMA_IN 18 23252942Sralph #define SCRIPT_RESUME_OUT 19 23352942Sralph #define SCRIPT_RESUME_DMA_OUT 20 23452942Sralph #define SCRIPT_RESUME_NO_DATA 21 23552889Sbostic 23652889Sbostic /* 23752889Sbostic * Scripts 23852889Sbostic */ 23952889Sbostic script_t asc_scripts[] = { 24052942Sralph /* start data in */ 24152889Sbostic {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAI), /* 0 */ 24252889Sbostic asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 24352942Sralph &asc_scripts[SCRIPT_DATA_IN + 1]}, 24452889Sbostic {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 1 */ 24552889Sbostic asc_last_dma_in, ASC_CMD_I_COMPLETE, 24652942Sralph &asc_scripts[SCRIPT_GET_STATUS]}, 24752889Sbostic 24858570Sralph /* continue data in after a chunk is finished */ 24952942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 2 */ 25052942Sralph asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 25152942Sralph &asc_scripts[SCRIPT_DATA_IN + 1]}, 25252942Sralph 25352942Sralph /* start data out */ 25452942Sralph {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAO), /* 3 */ 25552889Sbostic asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 25652942Sralph &asc_scripts[SCRIPT_DATA_OUT + 1]}, 25752942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 4 */ 25852889Sbostic asc_last_dma_out, ASC_CMD_I_COMPLETE, 25952942Sralph &asc_scripts[SCRIPT_GET_STATUS]}, 26052889Sbostic 26158570Sralph /* continue data out after a chunk is finished */ 26252942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 5 */ 26352942Sralph asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 26452942Sralph &asc_scripts[SCRIPT_DATA_OUT + 1]}, 26552942Sralph 26652889Sbostic /* simple command with no data transfer */ 26752942Sralph {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_STATUS), /* 6 */ 26852889Sbostic script_nop, ASC_CMD_I_COMPLETE, 26952942Sralph &asc_scripts[SCRIPT_GET_STATUS]}, 27052889Sbostic 27152889Sbostic /* get status and finish command */ 27252942Sralph {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 7 */ 27352889Sbostic asc_get_status, ASC_CMD_MSG_ACPT, 27452942Sralph &asc_scripts[SCRIPT_GET_STATUS + 1]}, 27552942Sralph {SCRIPT_MATCH(ASC_INT_DISC, 0), /* 8 */ 27652889Sbostic asc_end, ASC_CMD_NOP, 27752942Sralph &asc_scripts[SCRIPT_GET_STATUS + 1]}, 27852889Sbostic 27952889Sbostic /* message in */ 28052942Sralph {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 9 */ 28152942Sralph asc_msg_in, ASC_CMD_MSG_ACPT, 28252942Sralph &asc_scripts[SCRIPT_MSG_IN + 1]}, 28352942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 10 */ 28452889Sbostic script_nop, ASC_CMD_XFER_INFO, 28552942Sralph &asc_scripts[SCRIPT_MSG_IN]}, 28652889Sbostic 28752889Sbostic /* send synchonous negotiation reply */ 28852942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 11 */ 28952889Sbostic asc_replysync, ASC_CMD_XFER_INFO, 29052942Sralph &asc_scripts[SCRIPT_REPLY_SYNC]}, 29152889Sbostic 29252889Sbostic /* try to negotiate synchonous transfer parameters */ 29352889Sbostic {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 12 */ 29452889Sbostic asc_sendsync, ASC_CMD_XFER_INFO, 29553080Sralph &asc_scripts[SCRIPT_TRY_SYNC + 1]}, 29653080Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 13 */ 29752889Sbostic script_nop, ASC_CMD_XFER_INFO, 29853080Sralph &asc_scripts[SCRIPT_MSG_IN]}, 29953080Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_COMMAND), /* 14 */ 30053080Sralph script_nop, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 30153080Sralph &asc_scripts[SCRIPT_RESUME_NO_DATA]}, 30252889Sbostic 30352942Sralph /* handle a disconnect */ 30452942Sralph {SCRIPT_MATCH(ASC_INT_DISC, ASC_PHASE_DATAO), /* 15 */ 30552942Sralph asc_disconnect, ASC_CMD_ENABLE_SEL, 30652942Sralph &asc_scripts[SCRIPT_RESEL]}, 30752942Sralph 30852889Sbostic /* reselect sequence: this is just a placeholder so match fails */ 30952942Sralph {SCRIPT_MATCH(0, ASC_PHASE_MSG_IN), /* 16 */ 31052889Sbostic script_nop, ASC_CMD_MSG_ACPT, 31152942Sralph &asc_scripts[SCRIPT_RESEL]}, 31252889Sbostic 31352942Sralph /* resume data in after a message */ 31452942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 17 */ 31552942Sralph asc_resume_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 31652942Sralph &asc_scripts[SCRIPT_DATA_IN + 1]}, 31752942Sralph 31852942Sralph /* resume partial DMA data in after a message */ 31952942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 18 */ 32052889Sbostic asc_resume_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 32152942Sralph &asc_scripts[SCRIPT_DATA_IN + 1]}, 32252889Sbostic 32352942Sralph /* resume data out after a message */ 32452942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 19 */ 32552942Sralph asc_resume_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 32652942Sralph &asc_scripts[SCRIPT_DATA_OUT + 1]}, 32752942Sralph 32852942Sralph /* resume partial DMA data out after a message */ 32952942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 20 */ 33052889Sbostic asc_resume_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA, 33152942Sralph &asc_scripts[SCRIPT_DATA_OUT + 1]}, 33252942Sralph 33352942Sralph /* resume after a message when there is no more data */ 33452942Sralph {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 21 */ 33552942Sralph script_nop, ASC_CMD_I_COMPLETE, 33652942Sralph &asc_scripts[SCRIPT_GET_STATUS]}, 33752889Sbostic }; 33852889Sbostic 33952889Sbostic /* 34052889Sbostic * State kept for each active SCSI device. 34152889Sbostic */ 34252889Sbostic typedef struct scsi_state { 34352889Sbostic script_t *script; /* saved script while processing error */ 34452889Sbostic int statusByte; /* status byte returned during STATUS_PHASE */ 34552889Sbostic int error; /* errno to pass back to device driver */ 34652889Sbostic u_char *dmaBufAddr; /* DMA buffer address */ 34752889Sbostic u_int dmaBufSize; /* DMA buffer size */ 34852889Sbostic int dmalen; /* amount to transfer in this chunk */ 34952889Sbostic int dmaresid; /* amount not transfered if chunk suspended */ 35052889Sbostic int buflen; /* total remaining amount of data to transfer */ 35152889Sbostic char *buf; /* current pointer within scsicmd->buf */ 35252889Sbostic int flags; /* see below */ 35352889Sbostic int msglen; /* number of message bytes to read */ 35452889Sbostic int msgcnt; /* number of message bytes received */ 35552889Sbostic u_char sync_period; /* DMA synchronous period */ 35652889Sbostic u_char sync_offset; /* DMA synchronous xfer offset or 0 if async */ 35752889Sbostic u_char msg_out; /* next MSG_OUT byte to send */ 35852889Sbostic u_char msg_in[16]; /* buffer for multibyte messages */ 35952889Sbostic } State; 36052889Sbostic 36152889Sbostic /* state flags */ 36252889Sbostic #define DISCONN 0x01 /* true if currently disconnected from bus */ 36353080Sralph #define DMA_IN_PROGRESS 0x02 /* true if data DMA started */ 36452889Sbostic #define DMA_IN 0x04 /* true if reading from SCSI device */ 36552889Sbostic #define DMA_OUT 0x10 /* true if writing to SCSI device */ 36652889Sbostic #define DID_SYNC 0x20 /* true if synchronous offset was negotiated */ 36752889Sbostic #define TRY_SYNC 0x40 /* true if try neg. synchronous offset */ 36858658Sralph #define PARITY_ERR 0x80 /* true if parity error seen */ 36952889Sbostic 37052889Sbostic /* 37152889Sbostic * State kept for each active SCSI host interface (53C94). 37252889Sbostic */ 37352889Sbostic struct asc_softc { 37452889Sbostic asc_regmap_t *regs; /* chip address */ 37552889Sbostic volatile int *dmar; /* DMA address register address */ 37656819Sralph u_char *buff; /* RAM buffer address (uncached) */ 37752889Sbostic int myid; /* SCSI ID of this interface */ 37852889Sbostic int myidmask; /* ~(1 << myid) */ 37952889Sbostic int state; /* current SCSI connection state */ 38052889Sbostic int target; /* target SCSI ID if busy */ 38152889Sbostic script_t *script; /* next expected interrupt & action */ 38252889Sbostic ScsiCmd *cmd[ASC_NCMD]; /* active command indexed by SCSI ID */ 38352889Sbostic State st[ASC_NCMD]; /* state info for each active command */ 38456819Sralph void (*dma_start)(); /* Start dma routine */ 38556819Sralph void (*dma_end)(); /* End dma routine */ 38656819Sralph u_char *dma_next; 38756819Sralph int dma_xfer; /* Dma len still to go */ 38856819Sralph int min_period; /* Min transfer period clk/byte */ 38956819Sralph int max_period; /* Max transfer period clk/byte */ 39056819Sralph int ccf; /* CCF, whatever that really is? */ 39156819Sralph int timeout_250; /* 250ms timeout */ 39256819Sralph int tb_ticks; /* 4ns. ticks/tb channel ticks */ 39352889Sbostic } asc_softc[NASC]; 39452889Sbostic 39552889Sbostic #define ASC_STATE_IDLE 0 /* idle state */ 39652889Sbostic #define ASC_STATE_BUSY 1 /* selecting or currently connected */ 39752889Sbostic #define ASC_STATE_TARGET 2 /* currently selected as target */ 39852889Sbostic #define ASC_STATE_RESEL 3 /* currently waiting for reselect */ 39952889Sbostic 40052889Sbostic typedef struct asc_softc *asc_softc_t; 40152889Sbostic 40252889Sbostic /* 40356819Sralph * Dma operations. 40456819Sralph */ 40556819Sralph #define ASCDMA_READ 1 40656819Sralph #define ASCDMA_WRITE 2 40756819Sralph static void tb_dma_start(), tb_dma_end(), asic_dma_start(), asic_dma_end(); 40857233Sralph extern u_long asc_iomem; 40957233Sralph extern u_long asic_base; 41056819Sralph 41156819Sralph /* 41252889Sbostic * Definition of the controller for the auto-configuration program. 41352889Sbostic */ 41452889Sbostic int asc_probe(); 41552889Sbostic void asc_start(); 41652889Sbostic void asc_intr(); 41752889Sbostic struct driver ascdriver = { 41852889Sbostic "asc", asc_probe, asc_start, 0, asc_intr, 41952889Sbostic }; 42052889Sbostic 42152889Sbostic /* 42252889Sbostic * Test to see if device is present. 42352889Sbostic * Return true if found and initialized ok. 42452889Sbostic */ 42552889Sbostic asc_probe(cp) 42652889Sbostic register struct pmax_ctlr *cp; 42752889Sbostic { 42852889Sbostic register asc_softc_t asc; 42952889Sbostic register asc_regmap_t *regs; 43052889Sbostic int unit, id, s, i; 43157233Sralph int bufsiz; 43252889Sbostic 43352889Sbostic if ((unit = cp->pmax_unit) >= NASC) 43452889Sbostic return (0); 43552889Sbostic if (badaddr(cp->pmax_addr + ASC_OFFSET_53C94, 1)) 43652889Sbostic return (0); 43752889Sbostic asc = &asc_softc[unit]; 43852889Sbostic 43952889Sbostic /* 44052889Sbostic * Initialize hw descriptor, cache some pointers 44152889Sbostic */ 44252889Sbostic asc->regs = (asc_regmap_t *)(cp->pmax_addr + ASC_OFFSET_53C94); 44352889Sbostic 44456819Sralph /* 44556819Sralph * Set up machine dependencies. 44656819Sralph * 1) how to do dma 44756819Sralph * 2) timing based on turbochannel frequency 44856819Sralph */ 44956819Sralph switch (pmax_boardtype) { 45056819Sralph case DS_3MIN: 45156819Sralph case DS_MAXINE: 45257233Sralph case DS_3MAXPLUS: 45356819Sralph if (unit == 0) { 45457233Sralph asc->buff = (u_char *)MACH_PHYS_TO_UNCACHED(asc_iomem); 45557233Sralph bufsiz = 8192; 45657233Sralph *((volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base)) = -1; 45757233Sralph *((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1; 45857233Sralph *((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0; 45956819Sralph asc->dma_start = asic_dma_start; 46056819Sralph asc->dma_end = asic_dma_end; 46156819Sralph break; 46256819Sralph } 46356819Sralph /* 46456819Sralph * Fall through for turbochannel option. 46556819Sralph */ 46656819Sralph case DS_3MAX: 46756819Sralph default: 46856819Sralph asc->dmar = (volatile int *)(cp->pmax_addr + ASC_OFFSET_DMAR); 46956819Sralph asc->buff = (u_char *)(cp->pmax_addr + ASC_OFFSET_RAM); 47057233Sralph bufsiz = PER_TGT_DMA_SIZE; 47156819Sralph asc->dma_start = tb_dma_start; 47256819Sralph asc->dma_end = tb_dma_end; 47356819Sralph }; 47456819Sralph /* 47556819Sralph * Now for timing. The 3max has a 25Mhz tb whereas the 3min and 47656819Sralph * maxine are 12.5Mhz. 47756819Sralph */ 47856819Sralph switch (pmax_boardtype) { 47956819Sralph case DS_3MAX: 48057233Sralph case DS_3MAXPLUS: 48156819Sralph asc->min_period = ASC_MIN_PERIOD25; 48256819Sralph asc->max_period = ASC_MAX_PERIOD25; 48356819Sralph asc->ccf = ASC_CCF(25); 48456819Sralph asc->timeout_250 = ASC_TIMEOUT_250(25, asc->ccf); 48556819Sralph asc->tb_ticks = 10; 48656819Sralph break; 48756819Sralph case DS_3MIN: 48856819Sralph case DS_MAXINE: 48956819Sralph default: 49056819Sralph asc->min_period = ASC_MIN_PERIOD12; 49156819Sralph asc->max_period = ASC_MAX_PERIOD12; 49256819Sralph asc->ccf = ASC_CCF(13); 49356819Sralph asc->timeout_250 = ASC_TIMEOUT_250(13, asc->ccf); 49456819Sralph asc->tb_ticks = 20; 49556819Sralph break; 49656819Sralph }; 49756819Sralph 49852889Sbostic asc->state = ASC_STATE_IDLE; 49952889Sbostic asc->target = -1; 50052889Sbostic 50152889Sbostic regs = asc->regs; 50252889Sbostic 50352889Sbostic /* 50452889Sbostic * Reset chip, fully. Note that interrupts are already enabled. 50552889Sbostic */ 50652889Sbostic s = splbio(); 50752889Sbostic 50852889Sbostic /* preserve our ID for now */ 50952889Sbostic asc->myid = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID; 51052889Sbostic asc->myidmask = ~(1 << asc->myid); 51152889Sbostic 51252889Sbostic asc_reset(asc, regs); 51352889Sbostic 51452889Sbostic /* 51552889Sbostic * Our SCSI id on the bus. 51652889Sbostic * The user can set this via the prom on 3maxen/pmaxen. 51752889Sbostic * If this changes it is easy to fix: make a default that 51852889Sbostic * can be changed as boot arg. 51952889Sbostic */ 52052889Sbostic #ifdef unneeded 52152889Sbostic regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) | 52252889Sbostic (scsi_initiator_id[unit] & 0x7); 52352889Sbostic #endif 52452889Sbostic id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID; 52552889Sbostic splx(s); 52652889Sbostic 52752889Sbostic /* 52852889Sbostic * Statically partition the DMA buffer between targets. 52952889Sbostic * This way we will eventually be able to attach/detach 53052889Sbostic * drives on-fly. And 18k/target is plenty for normal use. 53152889Sbostic */ 53252889Sbostic 53352889Sbostic /* 53452889Sbostic * Give each target its own DMA buffer region. 53552889Sbostic * We may want to try ping ponging buffers later. 53652889Sbostic */ 53752889Sbostic for (i = 0; i < ASC_NCMD; i++) { 53857233Sralph asc->st[i].dmaBufAddr = asc->buff + bufsiz * i; 53957233Sralph asc->st[i].dmaBufSize = bufsiz; 54052889Sbostic } 54152889Sbostic printf("asc%d at nexus0 csr 0x%x priority %d SCSI id %d\n", 54252889Sbostic unit, cp->pmax_addr, cp->pmax_pri, id); 54352889Sbostic return (1); 54452889Sbostic } 54552889Sbostic 54652889Sbostic /* 54752889Sbostic * Start activity on a SCSI device. 54852889Sbostic * We maintain information on each device separately since devices can 54952889Sbostic * connect/disconnect during an operation. 55052889Sbostic */ 55152889Sbostic void 55252889Sbostic asc_start(scsicmd) 55352889Sbostic register ScsiCmd *scsicmd; /* command to start */ 55452889Sbostic { 55552889Sbostic register struct scsi_device *sdp = scsicmd->sd; 55652889Sbostic register asc_softc_t asc = &asc_softc[sdp->sd_ctlr]; 55752889Sbostic int s; 55852889Sbostic 55952889Sbostic s = splbio(); 56052889Sbostic /* 56152889Sbostic * Check if another command is already in progress. 56252889Sbostic * We may have to change this if we allow SCSI devices with 56352889Sbostic * separate LUNs. 56452889Sbostic */ 56552889Sbostic if (asc->cmd[sdp->sd_drive]) { 56652889Sbostic printf("asc%d: device %s busy at start\n", sdp->sd_ctlr, 56752889Sbostic sdp->sd_driver->d_name); 56852889Sbostic (*sdp->sd_driver->d_done)(scsicmd->unit, EBUSY, 56952889Sbostic scsicmd->buflen, 0); 57052889Sbostic splx(s); 57152889Sbostic } 57252889Sbostic asc->cmd[sdp->sd_drive] = scsicmd; 57352889Sbostic asc_startcmd(asc, sdp->sd_drive); 57452889Sbostic splx(s); 57552889Sbostic } 57652889Sbostic 57752889Sbostic static void 57852889Sbostic asc_reset(asc, regs) 57952889Sbostic asc_softc_t asc; 58052889Sbostic asc_regmap_t *regs; 58152889Sbostic { 58252889Sbostic 58352889Sbostic /* 58452889Sbostic * Reset chip and wait till done 58552889Sbostic */ 58652889Sbostic regs->asc_cmd = ASC_CMD_RESET; 58752889Sbostic MachEmptyWriteBuffer(); DELAY(25); 58852889Sbostic 58952889Sbostic /* spec says this is needed after reset */ 59052889Sbostic regs->asc_cmd = ASC_CMD_NOP; 59152889Sbostic MachEmptyWriteBuffer(); DELAY(25); 59252889Sbostic 59352889Sbostic /* 59452889Sbostic * Set up various chip parameters 59552889Sbostic */ 59656819Sralph regs->asc_ccf = asc->ccf; 59752889Sbostic MachEmptyWriteBuffer(); DELAY(25); 59856819Sralph regs->asc_sel_timo = asc->timeout_250; 59952889Sbostic /* restore our ID */ 60052889Sbostic regs->asc_cnfg1 = asc->myid | ASC_CNFG1_P_CHECK; 60157233Sralph /* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */ 60257233Sralph regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL; 60352889Sbostic regs->asc_cnfg3 = 0; 60452889Sbostic /* zero anything else */ 60552889Sbostic ASC_TC_PUT(regs, 0); 60656819Sralph regs->asc_syn_p = asc->min_period; 60752889Sbostic regs->asc_syn_o = 0; /* async for now */ 60852889Sbostic MachEmptyWriteBuffer(); 60952889Sbostic } 61052889Sbostic 61152889Sbostic /* 61252889Sbostic * Start a SCSI command on a target. 61352889Sbostic */ 61452889Sbostic static void 61552889Sbostic asc_startcmd(asc, target) 61652889Sbostic asc_softc_t asc; 61752889Sbostic int target; 61852889Sbostic { 61952889Sbostic register asc_regmap_t *regs; 62052889Sbostic register ScsiCmd *scsicmd; 62152889Sbostic register State *state; 62252889Sbostic int len; 62352889Sbostic 62452889Sbostic /* 62552889Sbostic * See if another target is currently selected on this SCSI bus. 62652889Sbostic */ 62752889Sbostic if (asc->target >= 0) 62852889Sbostic return; 62952889Sbostic 63052889Sbostic regs = asc->regs; 63152889Sbostic 63252889Sbostic /* 63358658Sralph * If a reselection is in progress, it is Ok to ignore it since 63458658Sralph * the ASC will automatically cancel the command and flush 63558658Sralph * the FIFO if the ASC is reselected before the command starts. 63658658Sralph * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if 63758658Sralph * a reselect occurs before starting the command. 63852889Sbostic */ 63952889Sbostic 64052889Sbostic asc->state = ASC_STATE_BUSY; 64152889Sbostic asc->target = target; 64252889Sbostic 64352889Sbostic /* cache some pointers */ 64452889Sbostic scsicmd = asc->cmd[target]; 64552889Sbostic state = &asc->st[target]; 64652889Sbostic 64752889Sbostic #ifdef DEBUG 64852889Sbostic if (asc_debug > 1) { 64952889Sbostic printf("asc_startcmd: %s target %d cmd %x len %d\n", 65052889Sbostic scsicmd->sd->sd_driver->d_name, target, 65152889Sbostic scsicmd->cmd[0], scsicmd->buflen); 65252889Sbostic } 65352889Sbostic #endif 65452889Sbostic 65552889Sbostic /* 65652889Sbostic * Init the chip and target state. 65752889Sbostic */ 65853080Sralph state->flags = state->flags & DID_SYNC; 65952889Sbostic state->error = 0; 66052889Sbostic state->script = (script_t *)0; 66152889Sbostic state->msg_out = SCSI_NO_OP; 66252889Sbostic 66352889Sbostic /* 66452889Sbostic * Copy command data to the DMA buffer. 66552889Sbostic */ 66660301Sralph len = scsicmd->cmdlen; 66752889Sbostic state->dmalen = len; 66860301Sralph bcopy(scsicmd->cmd, state->dmaBufAddr, len); 66952889Sbostic 67052889Sbostic /* check for simple SCSI command with no data transfer */ 67152889Sbostic if ((state->buflen = scsicmd->buflen) == 0) { 67252889Sbostic /* check for sync negotiation */ 67352889Sbostic if ((scsicmd->flags & SCSICMD_USE_SYNC) && 67452889Sbostic !(state->flags & DID_SYNC)) { 67552889Sbostic asc->script = &asc_scripts[SCRIPT_TRY_SYNC]; 67652889Sbostic state->flags |= TRY_SYNC; 67752889Sbostic } else 67852889Sbostic asc->script = &asc_scripts[SCRIPT_SIMPLE]; 67952889Sbostic state->buf = (char *)0; 68052889Sbostic } else if (scsicmd->flags & SCSICMD_DATA_TO_DEVICE) { 68152889Sbostic asc->script = &asc_scripts[SCRIPT_DATA_OUT]; 68253080Sralph state->buf = scsicmd->buf; 68352889Sbostic state->flags |= DMA_OUT; 68452889Sbostic } else { 68552889Sbostic asc->script = &asc_scripts[SCRIPT_DATA_IN]; 68652889Sbostic state->buf = scsicmd->buf; 68752889Sbostic state->flags |= DMA_IN; 68852889Sbostic } 68952889Sbostic 69058792Sralph #ifdef DEBUG 69158792Sralph asc_debug_cmd = scsicmd->cmd[0]; 69258792Sralph if (scsicmd->cmd[0] == SCSI_READ_EXT) { 69358792Sralph asc_debug_bn = (scsicmd->cmd[2] << 24) | 69458792Sralph (scsicmd->cmd[3] << 16) | 69558792Sralph (scsicmd->cmd[4] << 8) | 69658792Sralph scsicmd->cmd[5]; 69758792Sralph asc_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8]; 69858792Sralph } 69958792Sralph asc_logp->status = PACK(asc - asc_softc, 0, 0, asc_debug_cmd); 70058792Sralph asc_logp->target = asc->target; 70158792Sralph asc_logp->state = asc->script - asc_scripts; 70258792Sralph asc_logp->msg = SCSI_DIS_REC_IDENTIFY; 70358792Sralph asc_logp->resid = scsicmd->buflen; 70458792Sralph if (++asc_logp >= &asc_log[NLOG]) 70558792Sralph asc_logp = asc_log; 70658792Sralph #endif 70752889Sbostic 70860301Sralph /* preload the FIFO with the message to be sent */ 70960301Sralph regs->asc_fifo = SCSI_DIS_REC_IDENTIFY; 71060301Sralph MachEmptyWriteBuffer(); 71160301Sralph 71258792Sralph /* initialize the DMA */ 71356819Sralph (*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE); 71452889Sbostic ASC_TC_PUT(regs, len); 71556819Sralph readback(regs->asc_cmd); 71652889Sbostic 71752889Sbostic regs->asc_dbus_id = target; 71856819Sralph readback(regs->asc_dbus_id); 71952889Sbostic regs->asc_syn_p = state->sync_period; 72056819Sralph readback(regs->asc_syn_p); 72152889Sbostic regs->asc_syn_o = state->sync_offset; 72256819Sralph readback(regs->asc_syn_o); 72352889Sbostic 72452889Sbostic if (state->flags & TRY_SYNC) 72553080Sralph regs->asc_cmd = ASC_CMD_SEL_ATN_STOP; 72652889Sbostic else 72752889Sbostic regs->asc_cmd = ASC_CMD_SEL_ATN | ASC_CMD_DMA; 72856819Sralph readback(regs->asc_cmd); 72952889Sbostic } 73052889Sbostic 73152889Sbostic /* 73252889Sbostic * Interrupt routine 73352889Sbostic * Take interrupts from the chip 73452889Sbostic * 73552889Sbostic * Implementation: 73652889Sbostic * Move along the current command's script if 73752889Sbostic * all is well, invoke error handler if not. 73852889Sbostic */ 73952889Sbostic void 74052889Sbostic asc_intr(unit) 74152889Sbostic int unit; 74252889Sbostic { 74352889Sbostic register asc_softc_t asc = &asc_softc[unit]; 74452889Sbostic register asc_regmap_t *regs = asc->regs; 74552889Sbostic register State *state; 74652889Sbostic register script_t *scpt; 74752889Sbostic register int ss, ir, status; 74852889Sbostic 74952889Sbostic /* collect ephemeral information */ 75052889Sbostic status = regs->asc_status; 75153080Sralph again: 75252889Sbostic ss = regs->asc_ss; 75352889Sbostic ir = regs->asc_intr; /* this resets the previous two */ 75452889Sbostic scpt = asc->script; 75552889Sbostic 75652889Sbostic #ifdef DEBUG 75752889Sbostic asc_logp->status = PACK(unit, status, ss, ir); 75852889Sbostic asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1; 75952889Sbostic asc_logp->state = scpt - asc_scripts; 76052889Sbostic asc_logp->msg = -1; 76158658Sralph asc_logp->resid = 0; 76252889Sbostic if (++asc_logp >= &asc_log[NLOG]) 76352889Sbostic asc_logp = asc_log; 76452889Sbostic if (asc_debug > 2) 76552889Sbostic printf("asc_intr: status %x ss %x ir %x cond %d:%x\n", 76652889Sbostic status, ss, ir, scpt - asc_scripts, scpt->condition); 76752889Sbostic #endif 76852889Sbostic 76952889Sbostic /* check the expected state */ 77052889Sbostic if (SCRIPT_MATCH(ir, status) == scpt->condition) { 77152889Sbostic /* 77252889Sbostic * Perform the appropriate operation, then proceed. 77352889Sbostic */ 77452889Sbostic if ((*scpt->action)(asc, status, ss, ir)) { 77552889Sbostic regs->asc_cmd = scpt->command; 77656819Sralph readback(regs->asc_cmd); 77752889Sbostic asc->script = scpt->next; 77852889Sbostic } 77952889Sbostic goto done; 78052889Sbostic } 78152889Sbostic 78258658Sralph /* 78358658Sralph * Check for parity error. 78458658Sralph * Hardware will automatically set ATN 78558658Sralph * to request the device for a MSG_OUT phase. 78658658Sralph */ 78758658Sralph if (status & ASC_CSR_PE) { 78858658Sralph printf("asc%d: SCSI device %d: incomming parity error seen\n", 78958658Sralph asc - asc_softc, asc->target); 79058658Sralph asc->st[asc->target].flags |= PARITY_ERR; 79158658Sralph } 79258658Sralph 79358658Sralph /* 79458658Sralph * Check for gross error. 79558658Sralph * Probably a bug in a device driver. 79658658Sralph */ 79758658Sralph if (status & ASC_CSR_GE) { 79858658Sralph printf("asc%d: SCSI device %d: gross error\n", 79958658Sralph asc - asc_softc, asc->target); 80058658Sralph goto abort; 80158658Sralph } 80258658Sralph 80352889Sbostic /* check for message in or out */ 80452889Sbostic if ((ir & ~ASC_INT_FC) == ASC_INT_BS) { 80552889Sbostic register int len, fifo; 80652889Sbostic 80752889Sbostic state = &asc->st[asc->target]; 80852889Sbostic switch (ASC_PHASE(status)) { 80953080Sralph case ASC_PHASE_DATAI: 81053080Sralph case ASC_PHASE_DATAO: 81153080Sralph ASC_TC_GET(regs, len); 81253080Sralph fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 81353080Sralph printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n", 81453080Sralph state->buflen, state->dmalen, len, fifo); 81553080Sralph goto abort; 81653080Sralph 81752889Sbostic case ASC_PHASE_MSG_IN: 81852889Sbostic break; 81952889Sbostic 82052889Sbostic case ASC_PHASE_MSG_OUT: 82158658Sralph /* 82258658Sralph * Check for parity error. 82358658Sralph * Hardware will automatically set ATN 82458658Sralph * to request the device for a MSG_OUT phase. 82558658Sralph */ 82658658Sralph if (state->flags & PARITY_ERR) { 82758658Sralph state->flags &= ~PARITY_ERR; 82858658Sralph state->msg_out = SCSI_MESSAGE_PARITY_ERROR; 82958658Sralph /* reset message in counter */ 83058658Sralph state->msglen = 0; 83158658Sralph } else 83258658Sralph state->msg_out = SCSI_NO_OP; 83352889Sbostic regs->asc_fifo = state->msg_out; 83452889Sbostic regs->asc_cmd = ASC_CMD_XFER_INFO; 83556819Sralph readback(regs->asc_cmd); 83652889Sbostic goto done; 83752889Sbostic 83852889Sbostic case ASC_PHASE_STATUS: 83952889Sbostic /* probably an error in the SCSI command */ 84052889Sbostic asc->script = &asc_scripts[SCRIPT_GET_STATUS]; 84152889Sbostic regs->asc_cmd = ASC_CMD_I_COMPLETE; 84256819Sralph readback(regs->asc_cmd); 84352889Sbostic goto done; 84452889Sbostic 84552889Sbostic default: 84652889Sbostic goto abort; 84752889Sbostic } 84852889Sbostic 84952889Sbostic if (state->script) 85052889Sbostic goto abort; 85152889Sbostic 85252889Sbostic /* check for DMA in progress */ 85352889Sbostic ASC_TC_GET(regs, len); 85452889Sbostic fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 85552889Sbostic /* flush any data in the FIFO */ 85652889Sbostic if (fifo) { 85753080Sralph if (state->flags & DMA_OUT) 85853080Sralph len += fifo; 85953080Sralph else if (state->flags & DMA_IN) { 86053080Sralph u_char *cp; 86153080Sralph 86253080Sralph printf("asc_intr: IN: dmalen %d len %d fifo %d\n", 86353080Sralph state->dmalen, len, fifo); /* XXX */ 86453080Sralph len += fifo; 86553080Sralph cp = state->dmaBufAddr + (state->dmalen - len); 86653080Sralph while (fifo-- > 0) 86753080Sralph *cp++ = regs->asc_fifo; 86853080Sralph } else 86953080Sralph printf("asc_intr: dmalen %d len %d fifo %d\n", 87053080Sralph state->dmalen, len, fifo); /* XXX */ 87152889Sbostic regs->asc_cmd = ASC_CMD_FLUSH; 87256819Sralph readback(regs->asc_cmd); 87356819Sralph DELAY(2); 87452889Sbostic } 87565433Smckusick if (len && (state->flags & DMA_IN_PROGRESS)) { 87652889Sbostic /* save number of bytes still to be sent or received */ 87752889Sbostic state->dmaresid = len; 87865433Smckusick state->flags &= ~DMA_IN_PROGRESS; 879*67476Smckusick ASC_TC_PUT(regs, 0); 88058792Sralph #ifdef DEBUG 88158792Sralph if (asc_logp == asc_log) 88258792Sralph asc_log[NLOG - 1].resid = len; 88358792Sralph else 88458792Sralph asc_logp[-1].resid = len; 88558792Sralph #endif 88652889Sbostic /* setup state to resume to */ 88758792Sralph if (state->flags & DMA_IN) { 88858792Sralph /* 88958792Sralph * Since the ASC_CNFG3_SRB bit of the 89058792Sralph * cnfg3 register bit is not set, 89158792Sralph * we just transferred an extra byte. 89258792Sralph * Since we can't resume on an odd byte 89358792Sralph * boundary, we copy the valid data out 89458792Sralph * and resume DMA at the start address. 89558792Sralph */ 89658792Sralph if (len & 1) { 89758792Sralph printf("asc_intr: msg in len %d (fifo %d)\n", 89865433Smckusick len, fifo); /* XXX */ 89958792Sralph len = state->dmalen - len; 90058792Sralph goto do_in; 90158792Sralph } 90252889Sbostic state->script = 90352889Sbostic &asc_scripts[SCRIPT_RESUME_DMA_IN]; 90458792Sralph } else if (state->flags & DMA_OUT) 90552889Sbostic state->script = 90652889Sbostic &asc_scripts[SCRIPT_RESUME_DMA_OUT]; 90752889Sbostic else 90852889Sbostic state->script = asc->script; 90965433Smckusick } else if (state->flags & DMA_IN) { 910*67476Smckusick if (len) { 911*67476Smckusick printf("asc_intr: 1: bn %d len %d (fifo %d)\n", 912*67476Smckusick asc_debug_bn, len, fifo); /* XXX */ 913*67476Smckusick goto abort; 914*67476Smckusick } 91552889Sbostic /* setup state to resume to */ 91665433Smckusick if (state->flags & DMA_IN_PROGRESS) { 91765433Smckusick len = state->dmalen; 91865433Smckusick state->flags &= ~DMA_IN_PROGRESS; 91965433Smckusick do_in: 92065433Smckusick (*asc->dma_end)(asc, state, ASCDMA_READ); 92165433Smckusick bcopy(state->dmaBufAddr, state->buf, len); 92265433Smckusick state->buf += len; 92365433Smckusick state->buflen -= len; 92465433Smckusick } 92565433Smckusick if (state->buflen) 92653080Sralph state->script = 92765433Smckusick &asc_scripts[SCRIPT_RESUME_IN]; 92853080Sralph else 92965433Smckusick state->script = 93065433Smckusick &asc_scripts[SCRIPT_RESUME_NO_DATA]; 93165433Smckusick } else if (state->flags & DMA_OUT) { 932*67476Smckusick if (len) { 93365433Smckusick printf("asc_intr: 2: len %d (fifo %d)\n", len, 93465433Smckusick fifo); /* XXX */ 935*67476Smckusick goto abort; 936*67476Smckusick } 93765433Smckusick /* 93865433Smckusick * If this is the last chunk, the next expected 93965433Smckusick * state is to get status. 94065433Smckusick */ 94165433Smckusick if (state->flags & DMA_IN_PROGRESS) { 94265433Smckusick state->flags &= ~DMA_IN_PROGRESS; 94365433Smckusick (*asc->dma_end)(asc, state, ASCDMA_WRITE); 94465433Smckusick len = state->dmalen; 94565433Smckusick state->buf += len; 94665433Smckusick state->buflen -= len; 94765433Smckusick } 94865433Smckusick if (state->buflen) 94965433Smckusick state->script = 95065433Smckusick &asc_scripts[SCRIPT_RESUME_OUT]; 95165433Smckusick else 95265433Smckusick state->script = 95365433Smckusick &asc_scripts[SCRIPT_RESUME_NO_DATA]; 95465433Smckusick } else if (asc->script == &asc_scripts[SCRIPT_SIMPLE]) 95565433Smckusick state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA]; 95665433Smckusick else 95765433Smckusick state->script = asc->script; 95852889Sbostic 95952889Sbostic /* setup to receive a message */ 96052889Sbostic asc->script = &asc_scripts[SCRIPT_MSG_IN]; 96152889Sbostic state->msglen = 0; 96252889Sbostic regs->asc_cmd = ASC_CMD_XFER_INFO; 96356819Sralph readback(regs->asc_cmd); 96452889Sbostic goto done; 96552889Sbostic } 96652889Sbostic 96752889Sbostic /* check for SCSI bus reset */ 96852889Sbostic if (ir & ASC_INT_RESET) { 96952889Sbostic register int i; 97052889Sbostic 97152889Sbostic printf("asc%d: SCSI bus reset!!\n", asc - asc_softc); 97252889Sbostic /* need to flush any pending commands */ 97352889Sbostic for (i = 0; i < ASC_NCMD; i++) { 97452889Sbostic if (!asc->cmd[i]) 97552889Sbostic continue; 97652889Sbostic asc->st[i].error = EIO; 97752889Sbostic asc_end(asc, 0, 0, 0); 97852889Sbostic } 97952889Sbostic /* rearbitrate synchronous offset */ 98052889Sbostic for (i = 0; i < ASC_NCMD; i++) { 98152889Sbostic asc->st[i].sync_offset = 0; 98252889Sbostic asc->st[i].flags = 0; 98352889Sbostic } 98452889Sbostic asc->target = -1; 98552889Sbostic return; 98652889Sbostic } 98752889Sbostic 98852889Sbostic /* check for command errors */ 98952889Sbostic if (ir & ASC_INT_ILL) 99052889Sbostic goto abort; 99152889Sbostic 99252889Sbostic /* check for disconnect */ 99352889Sbostic if (ir & ASC_INT_DISC) { 99452889Sbostic state = &asc->st[asc->target]; 99552889Sbostic switch (ASC_SS(ss)) { 99652889Sbostic case 0: /* device did not respond */ 99758658Sralph /* check for one of the starting scripts */ 99858658Sralph switch (asc->script - asc_scripts) { 99958658Sralph case SCRIPT_TRY_SYNC: 100058658Sralph case SCRIPT_SIMPLE: 100158658Sralph case SCRIPT_DATA_IN: 100258658Sralph case SCRIPT_DATA_OUT: 100358658Sralph if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) { 100458658Sralph regs->asc_cmd = ASC_CMD_FLUSH; 100558658Sralph readback(regs->asc_cmd); 100658658Sralph } 100758658Sralph state->error = ENXIO; 100858658Sralph asc_end(asc, status, ss, ir); 100958658Sralph return; 101058658Sralph } 101158658Sralph /* FALLTHROUGH */ 101252889Sbostic 101352889Sbostic default: 101458658Sralph printf("asc%d: SCSI device %d: unexpected disconnect\n", 101558658Sralph asc - asc_softc, asc->target); 101657233Sralph /* 101757233Sralph * On rare occasions my RZ24 does a disconnect during 101857233Sralph * data in phase and the following seems to keep it 101957233Sralph * happy. 102057233Sralph * XXX Should a scsi disk ever do this?? 102157233Sralph */ 102257233Sralph asc->script = &asc_scripts[SCRIPT_RESEL]; 102357233Sralph asc->state = ASC_STATE_RESEL; 102457233Sralph state->flags |= DISCONN; 102557233Sralph regs->asc_cmd = ASC_CMD_ENABLE_SEL; 102657233Sralph readback(regs->asc_cmd); 102757233Sralph return; 102852889Sbostic } 102952889Sbostic } 103052889Sbostic 103152889Sbostic /* check for reselect */ 103252889Sbostic if (ir & ASC_INT_RESEL) { 103352889Sbostic unsigned fifo, id, msg; 103452889Sbostic 103552889Sbostic fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 103652889Sbostic if (fifo < 2) 103752889Sbostic goto abort; 103852889Sbostic /* read unencoded SCSI ID and convert to binary */ 103952889Sbostic msg = regs->asc_fifo & asc->myidmask; 104052889Sbostic for (id = 0; (msg & 1) == 0; id++) 104152889Sbostic msg >>= 1; 104252889Sbostic /* read identify message */ 104352889Sbostic msg = regs->asc_fifo; 104452889Sbostic #ifdef DEBUG 104552889Sbostic if (asc_logp == asc_log) 104652889Sbostic asc_log[NLOG - 1].msg = msg; 104752889Sbostic else 104852889Sbostic asc_logp[-1].msg = msg; 104952889Sbostic #endif 105052889Sbostic asc->state = ASC_STATE_BUSY; 105152889Sbostic asc->target = id; 105252889Sbostic state = &asc->st[id]; 105352889Sbostic asc->script = state->script; 105452889Sbostic state->script = (script_t *)0; 105552889Sbostic if (!(state->flags & DISCONN)) 105652889Sbostic goto abort; 105752889Sbostic state->flags &= ~DISCONN; 105853080Sralph regs->asc_syn_p = state->sync_period; 105953080Sralph regs->asc_syn_o = state->sync_offset; 106052889Sbostic regs->asc_cmd = ASC_CMD_MSG_ACPT; 106156819Sralph readback(regs->asc_cmd); 106252889Sbostic goto done; 106352889Sbostic } 106452889Sbostic 106552889Sbostic /* check if we are being selected as a target */ 106652889Sbostic if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN)) 106752889Sbostic goto abort; 106852889Sbostic 106958658Sralph /* 107058658Sralph * 'ir' must be just ASC_INT_FC. 107158658Sralph * This is normal if canceling an ASC_ENABLE_SEL. 107258658Sralph */ 107358658Sralph 107452889Sbostic done: 107552889Sbostic MachEmptyWriteBuffer(); 107653080Sralph /* watch out for HW race conditions and setup & hold time violations */ 107753080Sralph ir = regs->asc_status; 107853080Sralph while (ir != (status = regs->asc_status)) 107953080Sralph ir = status; 108053080Sralph if (status & ASC_CSR_INT) 108152889Sbostic goto again; 108252889Sbostic return; 108352889Sbostic 108452889Sbostic abort: 108552889Sbostic #ifdef DEBUG 108652889Sbostic asc_DumpLog("asc_intr"); 108752889Sbostic #endif 108852889Sbostic #if 0 108952889Sbostic panic("asc_intr"); 109052889Sbostic #else 1091*67476Smckusick boot(4); /* XXX */ 109252889Sbostic #endif 109352889Sbostic } 109452889Sbostic 109552889Sbostic /* 109652889Sbostic * All the many little things that the interrupt 109752889Sbostic * routine might switch to. 109852889Sbostic */ 109952889Sbostic 110052889Sbostic /* ARGSUSED */ 110152889Sbostic static int 110252889Sbostic script_nop(asc, status, ss, ir) 110352889Sbostic register asc_softc_t asc; 110452889Sbostic register int status, ss, ir; 110552889Sbostic { 110652889Sbostic return (1); 110752889Sbostic } 110852889Sbostic 110952889Sbostic /* ARGSUSED */ 111052889Sbostic static int 111152889Sbostic asc_get_status(asc, status, ss, ir) 111252889Sbostic register asc_softc_t asc; 111352889Sbostic register int status, ss, ir; 111452889Sbostic { 111552889Sbostic register asc_regmap_t *regs = asc->regs; 111652889Sbostic register int data; 111752889Sbostic 111852889Sbostic /* 111952889Sbostic * Get the last two bytes in the FIFO. 112052889Sbostic */ 112152889Sbostic if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) { 112252889Sbostic printf("asc_get_status: fifo cnt %d\n", data); /* XXX */ 112358658Sralph asc_DumpLog("get_status"); /* XXX */ 112452889Sbostic if (data < 2) { 112552889Sbostic asc->regs->asc_cmd = ASC_CMD_MSG_ACPT; 112656819Sralph readback(asc->regs->asc_cmd); 112752889Sbostic return (0); 112852889Sbostic } 112952889Sbostic do { 113052889Sbostic data = regs->asc_fifo; 113152889Sbostic } while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2); 113252889Sbostic } 113352889Sbostic 113452889Sbostic /* save the status byte */ 113552889Sbostic asc->st[asc->target].statusByte = data = regs->asc_fifo; 113652889Sbostic #ifdef DEBUG 113752889Sbostic if (asc_logp == asc_log) 113852889Sbostic asc_log[NLOG - 1].msg = data; 113952889Sbostic else 114052889Sbostic asc_logp[-1].msg = data; 114152889Sbostic #endif 114252889Sbostic 114352889Sbostic /* get the (presumed) command_complete message */ 114452889Sbostic if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE) 114552889Sbostic return (1); 114652889Sbostic 114752889Sbostic #ifdef DEBUG 114852889Sbostic printf("asc_get_status: status %x cmd %x\n", 114952889Sbostic asc->st[asc->target].statusByte, data); 115052889Sbostic asc_DumpLog("asc_get_status"); 115152889Sbostic #endif 115252889Sbostic return (0); 115352889Sbostic } 115452889Sbostic 115552889Sbostic /* ARGSUSED */ 115652889Sbostic static int 115752889Sbostic asc_end(asc, status, ss, ir) 115852889Sbostic register asc_softc_t asc; 115952889Sbostic register int status, ss, ir; 116052889Sbostic { 116152889Sbostic register ScsiCmd *scsicmd; 116252889Sbostic register State *state; 116352889Sbostic register int i, target; 116452889Sbostic 116552889Sbostic asc->state = ASC_STATE_IDLE; 116652889Sbostic target = asc->target; 116752889Sbostic asc->target = -1; 116852889Sbostic scsicmd = asc->cmd[target]; 116952889Sbostic asc->cmd[target] = (ScsiCmd *)0; 117052889Sbostic state = &asc->st[target]; 117152889Sbostic 117252889Sbostic #ifdef DEBUG 117352889Sbostic if (asc_debug > 1) { 117452889Sbostic printf("asc_end: %s target %d cmd %x err %d resid %d\n", 117552889Sbostic scsicmd->sd->sd_driver->d_name, target, 117652889Sbostic scsicmd->cmd[0], state->error, state->buflen); 117752889Sbostic } 117852889Sbostic #endif 117952889Sbostic #ifdef DIAGNOSTIC 118052889Sbostic if (target < 0 || !scsicmd) 118152889Sbostic panic("asc_end"); 118252889Sbostic #endif 118352889Sbostic 118452889Sbostic /* look for disconnected devices */ 118552889Sbostic for (i = 0; i < ASC_NCMD; i++) { 118652889Sbostic if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN)) 118752889Sbostic continue; 118852889Sbostic asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL; 118956819Sralph readback(asc->regs->asc_cmd); 119052889Sbostic asc->state = ASC_STATE_RESEL; 119152889Sbostic asc->script = &asc_scripts[SCRIPT_RESEL]; 119252889Sbostic break; 119352889Sbostic } 119452889Sbostic 119558658Sralph /* 119658658Sralph * Look for another device that is ready. 119758658Sralph * May want to keep last one started and increment for fairness 119858658Sralph * rather than always starting at zero. 119958658Sralph */ 120052889Sbostic for (i = 0; i < ASC_NCMD; i++) { 120152889Sbostic /* don't restart a disconnected command */ 120252889Sbostic if (!asc->cmd[i] || (asc->st[i].flags & DISCONN)) 120352889Sbostic continue; 120452889Sbostic asc_startcmd(asc, i); 120552889Sbostic break; 120652889Sbostic } 120752889Sbostic 120852889Sbostic /* signal device driver that the command is done */ 120952889Sbostic (*scsicmd->sd->sd_driver->d_done)(scsicmd->unit, state->error, 121052889Sbostic state->buflen, state->statusByte); 121152889Sbostic 121252889Sbostic return (0); 121352889Sbostic } 121452889Sbostic 121552889Sbostic /* ARGSUSED */ 121652889Sbostic static int 121752889Sbostic asc_dma_in(asc, status, ss, ir) 121852889Sbostic register asc_softc_t asc; 121952889Sbostic register int status, ss, ir; 122052889Sbostic { 122152889Sbostic register asc_regmap_t *regs = asc->regs; 122252889Sbostic register State *state = &asc->st[asc->target]; 122353080Sralph register int len; 122452889Sbostic 122552889Sbostic /* check for previous chunk in buffer */ 122653080Sralph if (state->flags & DMA_IN_PROGRESS) { 122752889Sbostic /* 122852889Sbostic * Only count bytes that have been copied to memory. 122952889Sbostic * There may be some bytes in the FIFO if synchonous transfers 123052889Sbostic * are in progress. 123152889Sbostic */ 123256819Sralph (*asc->dma_end)(asc, state, ASCDMA_READ); 123352889Sbostic ASC_TC_GET(regs, len); 123452889Sbostic len = state->dmalen - len; 123552889Sbostic bcopy(state->dmaBufAddr, state->buf, len); 123652889Sbostic state->buf += len; 123752889Sbostic state->buflen -= len; 123853080Sralph } 123952889Sbostic 124052942Sralph /* setup to start reading the next chunk */ 124152889Sbostic len = state->buflen; 1242*67476Smckusick #ifdef DEBUG 1243*67476Smckusick if (asc_logp == asc_log) 1244*67476Smckusick asc_log[NLOG - 1].resid = len; 1245*67476Smckusick else 1246*67476Smckusick asc_logp[-1].resid = len; 1247*67476Smckusick #endif 124852889Sbostic if (len > state->dmaBufSize) 124952889Sbostic len = state->dmaBufSize; 125052889Sbostic state->dmalen = len; 125156819Sralph (*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_READ); 125252889Sbostic ASC_TC_PUT(regs, len); 125352942Sralph #ifdef DEBUG 125452942Sralph if (asc_debug > 2) 125552942Sralph printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len); 125652942Sralph #endif 125752942Sralph 125852942Sralph /* check for next chunk */ 125953080Sralph state->flags |= DMA_IN_PROGRESS; 126052889Sbostic if (len != state->buflen) { 126152889Sbostic regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 126256819Sralph readback(regs->asc_cmd); 126352942Sralph asc->script = &asc_scripts[SCRIPT_CONTINUE_IN]; 126452889Sbostic return (0); 126552889Sbostic } 126652889Sbostic return (1); 126752889Sbostic } 126852889Sbostic 126952889Sbostic /* ARGSUSED */ 127052889Sbostic static int 127152889Sbostic asc_last_dma_in(asc, status, ss, ir) 127252889Sbostic register asc_softc_t asc; 127352889Sbostic register int status, ss, ir; 127452889Sbostic { 127552889Sbostic register asc_regmap_t *regs = asc->regs; 127652889Sbostic register State *state = &asc->st[asc->target]; 127752889Sbostic register int len, fifo; 127852889Sbostic 127952889Sbostic /* copy data from buffer to main memory */ 128056819Sralph (*asc->dma_end)(asc, state, ASCDMA_READ); 128152889Sbostic ASC_TC_GET(regs, len); 128252889Sbostic fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 128352889Sbostic #ifdef DEBUG 128452942Sralph if (asc_debug > 2) 128552889Sbostic printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n", 128652889Sbostic state->buflen, state->dmalen, len, fifo); 128752889Sbostic #endif 128852889Sbostic if (fifo) { 128952942Sralph /* device must be trying to send more than we expect */ 129052889Sbostic regs->asc_cmd = ASC_CMD_FLUSH; 129156819Sralph readback(regs->asc_cmd); 129252889Sbostic } 129353080Sralph state->flags &= ~DMA_IN_PROGRESS; 129452889Sbostic len = state->dmalen - len; 129552889Sbostic state->buflen -= len; 129652889Sbostic bcopy(state->dmaBufAddr, state->buf, len); 129752889Sbostic 129852889Sbostic return (1); 129952889Sbostic } 130052889Sbostic 130152889Sbostic /* ARGSUSED */ 130252889Sbostic static int 130352942Sralph asc_resume_in(asc, status, ss, ir) 130452942Sralph register asc_softc_t asc; 130552942Sralph register int status, ss, ir; 130652942Sralph { 130752942Sralph register asc_regmap_t *regs = asc->regs; 130852942Sralph register State *state = &asc->st[asc->target]; 130952942Sralph register int len; 131052942Sralph 131152942Sralph /* setup to start reading the next chunk */ 131252942Sralph len = state->buflen; 1313*67476Smckusick #ifdef DEBUG 1314*67476Smckusick if (asc_logp == asc_log) 1315*67476Smckusick asc_log[NLOG - 1].resid = len; 1316*67476Smckusick else 1317*67476Smckusick asc_logp[-1].resid = len; 1318*67476Smckusick #endif 131952942Sralph if (len > state->dmaBufSize) 132052942Sralph len = state->dmaBufSize; 132152942Sralph state->dmalen = len; 132256819Sralph (*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_READ); 132352942Sralph ASC_TC_PUT(regs, len); 132452942Sralph #ifdef DEBUG 132552942Sralph if (asc_debug > 2) 132652942Sralph printf("asc_resume_in: buflen %d, len %d\n", state->buflen, 132752942Sralph len); 132852942Sralph #endif 132952942Sralph 133052942Sralph /* check for next chunk */ 133153080Sralph state->flags |= DMA_IN_PROGRESS; 133252942Sralph if (len != state->buflen) { 133352942Sralph regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 133456819Sralph readback(regs->asc_cmd); 133552942Sralph asc->script = &asc_scripts[SCRIPT_CONTINUE_IN]; 133652942Sralph return (0); 133752942Sralph } 133852942Sralph return (1); 133952942Sralph } 134052942Sralph 134152942Sralph /* ARGSUSED */ 134252942Sralph static int 134352889Sbostic asc_resume_dma_in(asc, status, ss, ir) 134452889Sbostic register asc_softc_t asc; 134552889Sbostic register int status, ss, ir; 134652889Sbostic { 134752889Sbostic register asc_regmap_t *regs = asc->regs; 134852889Sbostic register State *state = &asc->st[asc->target]; 134952889Sbostic register int len, off; 135052889Sbostic 135152889Sbostic /* setup to finish reading the current chunk */ 135252889Sbostic len = state->dmaresid; 135352889Sbostic off = state->dmalen - len; 135452889Sbostic if ((off & 1) && state->sync_offset) { 135552889Sbostic printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n", 135652889Sbostic state->dmalen, len, off); /* XXX */ 135752889Sbostic regs->asc_res_fifo = state->dmaBufAddr[off]; 135852889Sbostic } 1359*67476Smckusick #ifdef DEBUG 1360*67476Smckusick if (asc_logp == asc_log) 1361*67476Smckusick asc_log[NLOG - 1].resid = len; 1362*67476Smckusick else 1363*67476Smckusick asc_logp[-1].resid = len; 1364*67476Smckusick #endif 136556819Sralph (*asc->dma_start)(asc, state, state->dmaBufAddr + off, ASCDMA_READ); 136652889Sbostic ASC_TC_PUT(regs, len); 136752942Sralph #ifdef DEBUG 136852942Sralph if (asc_debug > 2) 136952942Sralph printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n", 137052942Sralph state->dmalen, state->buflen, len, off); 137152942Sralph #endif 137252942Sralph 137352942Sralph /* check for next chunk */ 137453080Sralph state->flags |= DMA_IN_PROGRESS; 137552889Sbostic if (state->dmalen != state->buflen) { 137652889Sbostic regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 137756819Sralph readback(regs->asc_cmd); 137852942Sralph asc->script = &asc_scripts[SCRIPT_CONTINUE_IN]; 137952889Sbostic return (0); 138052889Sbostic } 138152889Sbostic return (1); 138252889Sbostic } 138352889Sbostic 138452889Sbostic /* ARGSUSED */ 138552889Sbostic static int 138652889Sbostic asc_dma_out(asc, status, ss, ir) 138752889Sbostic register asc_softc_t asc; 138852889Sbostic register int status, ss, ir; 138952889Sbostic { 139052889Sbostic register asc_regmap_t *regs = asc->regs; 139152889Sbostic register State *state = &asc->st[asc->target]; 139252889Sbostic register int len, fifo; 139352889Sbostic 139453080Sralph if (state->flags & DMA_IN_PROGRESS) { 139552889Sbostic /* check to be sure previous chunk was finished */ 139652889Sbostic ASC_TC_GET(regs, len); 139752889Sbostic fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 139852889Sbostic if (len || fifo) 139952889Sbostic printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n", 140052889Sbostic state->buflen, state->dmalen, len, fifo); /* XXX */ 140152889Sbostic len += fifo; 140252889Sbostic len = state->dmalen - len; 140353080Sralph state->buf += len; 140452889Sbostic state->buflen -= len; 140553080Sralph } 140652889Sbostic 140758792Sralph /* setup for this chunk */ 140853080Sralph len = state->buflen; 1409*67476Smckusick #ifdef DEBUG 1410*67476Smckusick if (asc_logp == asc_log) 1411*67476Smckusick asc_log[NLOG - 1].resid = len; 1412*67476Smckusick else 1413*67476Smckusick asc_logp[-1].resid = len; 1414*67476Smckusick #endif 141553080Sralph if (len > state->dmaBufSize) 141653080Sralph len = state->dmaBufSize; 141753080Sralph state->dmalen = len; 141853080Sralph bcopy(state->buf, state->dmaBufAddr, len); 141956819Sralph (*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE); 142052942Sralph ASC_TC_PUT(regs, len); 142152889Sbostic #ifdef DEBUG 142252889Sbostic if (asc_debug > 2) 142352942Sralph printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len); 142452889Sbostic #endif 142552889Sbostic 142652889Sbostic /* check for next chunk */ 142753080Sralph state->flags |= DMA_IN_PROGRESS; 142852889Sbostic if (len != state->buflen) { 142952889Sbostic regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 143056819Sralph readback(regs->asc_cmd); 143152942Sralph asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT]; 143252889Sbostic return (0); 143352889Sbostic } 143452889Sbostic return (1); 143552889Sbostic } 143652889Sbostic 143752889Sbostic /* ARGSUSED */ 143852889Sbostic static int 143952889Sbostic asc_last_dma_out(asc, status, ss, ir) 144052889Sbostic register asc_softc_t asc; 144152889Sbostic register int status, ss, ir; 144252889Sbostic { 144352889Sbostic register asc_regmap_t *regs = asc->regs; 144452889Sbostic register State *state = &asc->st[asc->target]; 144552889Sbostic register int len, fifo; 144652889Sbostic 144752889Sbostic ASC_TC_GET(regs, len); 144852889Sbostic fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT; 144952889Sbostic #ifdef DEBUG 145052889Sbostic if (asc_debug > 2) 145152889Sbostic printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n", 145253080Sralph state->buflen, state->dmalen, len, fifo); 145352942Sralph #endif 145452942Sralph if (fifo) { 145552942Sralph len += fifo; 145652942Sralph regs->asc_cmd = ASC_CMD_FLUSH; 145756819Sralph readback(regs->asc_cmd); 145858792Sralph printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n", 145958792Sralph state->buflen, state->dmalen, len, fifo); 146052942Sralph } 146153080Sralph state->flags &= ~DMA_IN_PROGRESS; 146252889Sbostic len = state->dmalen - len; 146352889Sbostic state->buflen -= len; 146452889Sbostic return (1); 146552889Sbostic } 146652889Sbostic 146752889Sbostic /* ARGSUSED */ 146852889Sbostic static int 146952942Sralph asc_resume_out(asc, status, ss, ir) 147052942Sralph register asc_softc_t asc; 147152942Sralph register int status, ss, ir; 147252942Sralph { 147352942Sralph register asc_regmap_t *regs = asc->regs; 147452942Sralph register State *state = &asc->st[asc->target]; 147552942Sralph register int len; 147652942Sralph 147758792Sralph /* setup for this chunk */ 147852942Sralph len = state->buflen; 1479*67476Smckusick #ifdef DEBUG 1480*67476Smckusick if (asc_logp == asc_log) 1481*67476Smckusick asc_log[NLOG - 1].resid = len; 1482*67476Smckusick else 1483*67476Smckusick asc_logp[-1].resid = len; 1484*67476Smckusick #endif 148552942Sralph if (len > state->dmaBufSize) 148652942Sralph len = state->dmaBufSize; 148752942Sralph state->dmalen = len; 148852942Sralph bcopy(state->buf, state->dmaBufAddr, len); 148956819Sralph (*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE); 149052942Sralph ASC_TC_PUT(regs, len); 149152942Sralph #ifdef DEBUG 149252942Sralph if (asc_debug > 2) 149352942Sralph printf("asc_resume_out: buflen %d, len %d\n", state->buflen, 149452942Sralph len); 149552942Sralph #endif 149652942Sralph 149752942Sralph /* check for next chunk */ 149853080Sralph state->flags |= DMA_IN_PROGRESS; 149952942Sralph if (len != state->buflen) { 150052942Sralph regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 150156819Sralph readback(regs->asc_cmd); 150252942Sralph asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT]; 150352942Sralph return (0); 150452942Sralph } 150552942Sralph return (1); 150652942Sralph } 150752942Sralph 150852942Sralph /* ARGSUSED */ 150952942Sralph static int 151052889Sbostic asc_resume_dma_out(asc, status, ss, ir) 151152889Sbostic register asc_softc_t asc; 151252889Sbostic register int status, ss, ir; 151352889Sbostic { 151452889Sbostic register asc_regmap_t *regs = asc->regs; 151552889Sbostic register State *state = &asc->st[asc->target]; 151652889Sbostic register int len, off; 151752889Sbostic 151852889Sbostic /* setup to finish writing this chunk */ 151952889Sbostic len = state->dmaresid; 152052889Sbostic off = state->dmalen - len; 152152889Sbostic if (off & 1) { 152252889Sbostic printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n", 152352889Sbostic state->dmalen, len, off); /* XXX */ 152452889Sbostic regs->asc_fifo = state->dmaBufAddr[off]; 152552889Sbostic off++; 152652889Sbostic len--; 152752889Sbostic } 1528*67476Smckusick #ifdef DEBUG 1529*67476Smckusick if (asc_logp == asc_log) 1530*67476Smckusick asc_log[NLOG - 1].resid = len; 1531*67476Smckusick else 1532*67476Smckusick asc_logp[-1].resid = len; 1533*67476Smckusick #endif 153456819Sralph (*asc->dma_start)(asc, state, state->dmaBufAddr + off, ASCDMA_WRITE); 153552889Sbostic ASC_TC_PUT(regs, len); 153652942Sralph #ifdef DEBUG 153752942Sralph if (asc_debug > 2) 153852942Sralph printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n", 153952942Sralph state->dmalen, state->buflen, len, off); 154052942Sralph #endif 154152942Sralph 154252942Sralph /* check for next chunk */ 154353080Sralph state->flags |= DMA_IN_PROGRESS; 154452889Sbostic if (state->dmalen != state->buflen) { 154552889Sbostic regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA; 154656819Sralph readback(regs->asc_cmd); 154752942Sralph asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT]; 154852889Sbostic return (0); 154952889Sbostic } 155052889Sbostic return (1); 155152889Sbostic } 155252889Sbostic 155352889Sbostic /* ARGSUSED */ 155452889Sbostic static int 155552889Sbostic asc_sendsync(asc, status, ss, ir) 155652889Sbostic register asc_softc_t asc; 155752889Sbostic register int status, ss, ir; 155852889Sbostic { 155952889Sbostic register asc_regmap_t *regs = asc->regs; 156053080Sralph register State *state = &asc->st[asc->target]; 156152889Sbostic 156253080Sralph /* send the extended synchronous negotiation message */ 156352889Sbostic regs->asc_fifo = SCSI_EXTENDED_MSG; 156452889Sbostic MachEmptyWriteBuffer(); 156552889Sbostic regs->asc_fifo = 3; 156652889Sbostic MachEmptyWriteBuffer(); 156752889Sbostic regs->asc_fifo = SCSI_SYNCHRONOUS_XFER; 156852889Sbostic MachEmptyWriteBuffer(); 156952889Sbostic regs->asc_fifo = SCSI_MIN_PERIOD; 157052889Sbostic MachEmptyWriteBuffer(); 157152889Sbostic regs->asc_fifo = ASC_MAX_OFFSET; 157253080Sralph /* state to resume after we see the sync reply message */ 157353080Sralph state->script = asc->script + 2; 157453080Sralph state->msglen = 0; 157552889Sbostic return (1); 157652889Sbostic } 157752889Sbostic 157852889Sbostic /* ARGSUSED */ 157952889Sbostic static int 158052889Sbostic asc_replysync(asc, status, ss, ir) 158152889Sbostic register asc_softc_t asc; 158252889Sbostic register int status, ss, ir; 158352889Sbostic { 158452889Sbostic register asc_regmap_t *regs = asc->regs; 158552889Sbostic register State *state = &asc->st[asc->target]; 158652889Sbostic 158752889Sbostic #ifdef DEBUG 158852889Sbostic if (asc_debug > 2) 158952889Sbostic printf("asc_replysync: %x %x\n", 159056819Sralph asc_to_scsi_period[state->sync_period] * asc->tb_ticks, 159152889Sbostic state->sync_offset); 159252889Sbostic #endif 159352889Sbostic /* send synchronous transfer in response to a request */ 159452889Sbostic regs->asc_fifo = SCSI_EXTENDED_MSG; 159552889Sbostic MachEmptyWriteBuffer(); 159652889Sbostic regs->asc_fifo = 3; 159752889Sbostic MachEmptyWriteBuffer(); 159852889Sbostic regs->asc_fifo = SCSI_SYNCHRONOUS_XFER; 159952889Sbostic MachEmptyWriteBuffer(); 160056819Sralph regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks; 160152889Sbostic MachEmptyWriteBuffer(); 160252889Sbostic regs->asc_fifo = state->sync_offset; 160352889Sbostic regs->asc_cmd = ASC_CMD_XFER_INFO; 160456819Sralph readback(regs->asc_cmd); 160552889Sbostic 160652889Sbostic /* return to the appropriate script */ 160752889Sbostic if (!state->script) { 160852889Sbostic #ifdef DEBUG 160952889Sbostic asc_DumpLog("asc_replsync"); 161052889Sbostic #endif 161152889Sbostic panic("asc_replysync"); 161252889Sbostic } 161352889Sbostic asc->script = state->script; 161452889Sbostic state->script = (script_t *)0; 161552889Sbostic return (0); 161652889Sbostic } 161752889Sbostic 161852889Sbostic /* ARGSUSED */ 161952889Sbostic static int 162052942Sralph asc_msg_in(asc, status, ss, ir) 162152889Sbostic register asc_softc_t asc; 162252889Sbostic register int status, ss, ir; 162352889Sbostic { 162452889Sbostic register asc_regmap_t *regs = asc->regs; 162552889Sbostic register State *state = &asc->st[asc->target]; 162652889Sbostic register int msg; 162752889Sbostic int i; 162852889Sbostic 162952889Sbostic /* read one message byte */ 163052889Sbostic msg = regs->asc_fifo; 163152889Sbostic #ifdef DEBUG 163252889Sbostic if (asc_logp == asc_log) 163352889Sbostic asc_log[NLOG - 1].msg = msg; 163452889Sbostic else 163552889Sbostic asc_logp[-1].msg = msg; 163652889Sbostic #endif 163752889Sbostic 163852889Sbostic /* check for multi-byte message */ 163952889Sbostic if (state->msglen != 0) { 164052889Sbostic /* first byte is the message length */ 164152889Sbostic if (state->msglen < 0) { 164252889Sbostic state->msglen = msg; 164352889Sbostic return (1); 164452889Sbostic } 164552889Sbostic if (state->msgcnt >= state->msglen) 164652889Sbostic goto abort; 164752889Sbostic state->msg_in[state->msgcnt++] = msg; 164852889Sbostic 164952889Sbostic /* did we just read the last byte of the message? */ 165052889Sbostic if (state->msgcnt != state->msglen) 165152889Sbostic return (1); 165252889Sbostic 165352889Sbostic /* process an extended message */ 165452889Sbostic #ifdef DEBUG 165552889Sbostic if (asc_debug > 2) 165652942Sralph printf("asc_msg_in: msg %x %x %x\n", 165752889Sbostic state->msg_in[0], 165852889Sbostic state->msg_in[1], 165952889Sbostic state->msg_in[2]); 166052889Sbostic #endif 166152889Sbostic switch (state->msg_in[0]) { 166252889Sbostic case SCSI_SYNCHRONOUS_XFER: 166352889Sbostic state->flags |= DID_SYNC; 166452889Sbostic state->sync_offset = state->msg_in[2]; 166552889Sbostic 166652889Sbostic /* convert SCSI period to ASC period */ 166756819Sralph i = state->msg_in[1] / asc->tb_ticks; 166856819Sralph if (i < asc->min_period) 166956819Sralph i = asc->min_period; 167056819Sralph else if (i >= asc->max_period) { 167152889Sbostic /* can't do sync transfer, period too long */ 167252889Sbostic printf("asc%d: SCSI device %d: sync xfer period too long (%d)\n", 167352889Sbostic asc - asc_softc, asc->target, i); 167456819Sralph i = asc->max_period; 167552889Sbostic state->sync_offset = 0; 167652889Sbostic } 167756819Sralph if ((i * asc->tb_ticks) != state->msg_in[1]) 167852889Sbostic i++; 167952889Sbostic state->sync_period = i & 0x1F; 168052889Sbostic 168152889Sbostic /* 168252889Sbostic * If this is a request, check minimums and 168352889Sbostic * send back an acknowledge. 168452889Sbostic */ 168552889Sbostic if (!(state->flags & TRY_SYNC)) { 168652889Sbostic regs->asc_cmd = ASC_CMD_SET_ATN; 168756819Sralph readback(regs->asc_cmd); 168852889Sbostic 168956819Sralph if (state->sync_period < asc->min_period) 169052889Sbostic state->sync_period = 169156819Sralph asc->min_period; 169252889Sbostic if (state->sync_offset > ASC_MAX_OFFSET) 169352889Sbostic state->sync_offset = 169452889Sbostic ASC_MAX_OFFSET; 169552889Sbostic asc->script = &asc_scripts[SCRIPT_REPLY_SYNC]; 169652889Sbostic regs->asc_syn_p = state->sync_period; 169756819Sralph readback(regs->asc_syn_p); 169852889Sbostic regs->asc_syn_o = state->sync_offset; 169956819Sralph readback(regs->asc_syn_o); 170052889Sbostic regs->asc_cmd = ASC_CMD_MSG_ACPT; 170156819Sralph readback(regs->asc_cmd); 170252889Sbostic return (0); 170352889Sbostic } 170452889Sbostic 170552889Sbostic regs->asc_syn_p = state->sync_period; 170656819Sralph readback(regs->asc_syn_p); 170752889Sbostic regs->asc_syn_o = state->sync_offset; 170856819Sralph readback(regs->asc_syn_o); 170952889Sbostic goto done; 171052889Sbostic 171152889Sbostic default: 171252889Sbostic printf("asc%d: SCSI device %d: rejecting extended message 0x%x\n", 171352889Sbostic asc - asc_softc, asc->target, 171452889Sbostic state->msg_in[0]); 171552889Sbostic goto reject; 171652889Sbostic } 171752889Sbostic } 171852889Sbostic 171952889Sbostic /* process first byte of a message */ 172052889Sbostic #ifdef DEBUG 172152889Sbostic if (asc_debug > 2) 172252942Sralph printf("asc_msg_in: msg %x\n", msg); 172352889Sbostic #endif 172452889Sbostic switch (msg) { 172552889Sbostic #if 0 172652889Sbostic case SCSI_MESSAGE_REJECT: 172752889Sbostic printf(" did not like SYNCH xfer "); /* XXX */ 172852889Sbostic state->flags |= DID_SYNC; 172952889Sbostic regs->asc_cmd = ASC_CMD_MSG_ACPT; 173056819Sralph readback(regs->asc_cmd); 173152889Sbostic status = asc_wait(regs, ASC_CSR_INT); 173252889Sbostic ir = regs->asc_intr; 173352889Sbostic /* some just break out here, some dont */ 173452889Sbostic if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) { 173552889Sbostic regs->asc_fifo = SCSI_ABORT; 173652889Sbostic regs->asc_cmd = ASC_CMD_XFER_INFO; 173756819Sralph readback(regs->asc_cmd); 173852889Sbostic status = asc_wait(regs, ASC_CSR_INT); 173952889Sbostic ir = regs->asc_intr; 174052889Sbostic } 174152889Sbostic if (ir & ASC_INT_DISC) { 174252889Sbostic asc_end(asc, status, 0, ir); 174352889Sbostic return (0); 174452889Sbostic } 174552889Sbostic goto status; 174652889Sbostic #endif 174752889Sbostic 174852889Sbostic case SCSI_EXTENDED_MSG: /* read an extended message */ 174952889Sbostic /* setup to read message length next */ 175052889Sbostic state->msglen = -1; 175152889Sbostic state->msgcnt = 0; 175252889Sbostic return (1); 175352889Sbostic 175452889Sbostic case SCSI_NO_OP: 175552889Sbostic break; 175652889Sbostic 175752889Sbostic case SCSI_SAVE_DATA_POINTER: 175852889Sbostic /* expect another message */ 175952889Sbostic return (1); 176052889Sbostic 176152889Sbostic case SCSI_RESTORE_POINTERS: 176252889Sbostic /* 176352889Sbostic * Need to do the following if resuming synchonous data in 176452889Sbostic * on an odd byte boundary. 176552889Sbostic regs->asc_cnfg2 |= ASC_CNFG2_RFB; 176652889Sbostic */ 176752889Sbostic break; 176852889Sbostic 176952889Sbostic case SCSI_DISCONNECT: 177052889Sbostic if (state->flags & DISCONN) 177152889Sbostic goto abort; 177252889Sbostic state->flags |= DISCONN; 177352942Sralph regs->asc_cmd = ASC_CMD_MSG_ACPT; 177456819Sralph readback(regs->asc_cmd); 177552942Sralph asc->script = &asc_scripts[SCRIPT_DISCONNECT]; 177652942Sralph return (0); 177752889Sbostic 177852889Sbostic default: 177952889Sbostic printf("asc%d: SCSI device %d: rejecting message 0x%x\n", 178052889Sbostic asc - asc_softc, asc->target, msg); 178152889Sbostic reject: 178252889Sbostic /* request a message out before acknowledging this message */ 178352889Sbostic state->msg_out = SCSI_MESSAGE_REJECT; 178452889Sbostic regs->asc_cmd = ASC_CMD_SET_ATN; 178556819Sralph readback(regs->asc_cmd); 178652889Sbostic } 178752889Sbostic 178852889Sbostic done: 178952889Sbostic /* return to original script */ 179052889Sbostic regs->asc_cmd = ASC_CMD_MSG_ACPT; 179156819Sralph readback(regs->asc_cmd); 179252889Sbostic if (!state->script) { 179352889Sbostic abort: 179452889Sbostic #ifdef DEBUG 179552942Sralph asc_DumpLog("asc_msg_in"); 179652889Sbostic #endif 179752942Sralph panic("asc_msg_in"); 179852889Sbostic } 179952889Sbostic asc->script = state->script; 180052889Sbostic state->script = (script_t *)0; 180152889Sbostic return (0); 180252889Sbostic } 180352889Sbostic 180452942Sralph /* ARGSUSED */ 180552942Sralph static int 180652942Sralph asc_disconnect(asc, status, ss, ir) 180752942Sralph register asc_softc_t asc; 180852942Sralph register int status, ss, ir; 180952942Sralph { 181052942Sralph register State *state = &asc->st[asc->target]; 181152942Sralph 181258658Sralph #ifdef DIAGNOSTIC 181358658Sralph if (!(state->flags & DISCONN)) { 181458658Sralph printf("asc_disconnect: device %d: DISCONN not set!\n", 181558658Sralph asc->target); 181658658Sralph } 181758658Sralph #endif 181852942Sralph asc->target = -1; 181952942Sralph asc->state = ASC_STATE_RESEL; 182052942Sralph return (1); 182152942Sralph } 182252942Sralph 182356819Sralph /* 182458792Sralph * DMA handling routines. For a turbochannel device, just set the dmar. 182558792Sralph * For the I/O ASIC, handle the actual DMA interface. 182656819Sralph */ 182756819Sralph static void 182856819Sralph tb_dma_start(asc, state, cp, flag) 182956819Sralph asc_softc_t asc; 183056819Sralph State *state; 183156819Sralph caddr_t cp; 183256819Sralph int flag; 183356819Sralph { 183456819Sralph 183556819Sralph if (flag == ASCDMA_WRITE) 183656819Sralph *asc->dmar = ASC_DMAR_WRITE | ASC_DMA_ADDR(cp); 183756819Sralph else 183856819Sralph *asc->dmar = ASC_DMA_ADDR(cp); 183956819Sralph } 184056819Sralph 184156819Sralph static void 184256819Sralph tb_dma_end(asc, state, flag) 184356819Sralph asc_softc_t asc; 184456819Sralph State *state; 184556819Sralph int flag; 184656819Sralph { 184756819Sralph 184856819Sralph } 184956819Sralph 185056819Sralph static void 185156819Sralph asic_dma_start(asc, state, cp, flag) 185256819Sralph asc_softc_t asc; 185356819Sralph State *state; 185456819Sralph caddr_t cp; 185556819Sralph int flag; 185656819Sralph { 185756819Sralph register volatile u_int *ssr = (volatile u_int *) 185857233Sralph ASIC_REG_CSR(asic_base); 185956819Sralph u_int phys, nphys; 186056819Sralph 186156819Sralph /* stop DMA engine first */ 186256819Sralph *ssr &= ~ASIC_CSR_DMAEN_SCSI; 186358658Sralph *((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0; 186456819Sralph 186556819Sralph phys = MACH_CACHED_TO_PHYS(cp); 186656819Sralph cp = (caddr_t)pmax_trunc_page(cp + NBPG); 186756819Sralph nphys = MACH_CACHED_TO_PHYS(cp); 186856819Sralph 186956819Sralph asc->dma_next = cp; 187056819Sralph asc->dma_xfer = state->dmalen - (nphys - phys); 187156819Sralph 187257233Sralph *(volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base) = 187356819Sralph ASIC_DMA_ADDR(phys); 187457233Sralph *(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) = 187556819Sralph ASIC_DMA_ADDR(nphys); 187656819Sralph if (flag == ASCDMA_READ) 187756819Sralph *ssr |= ASIC_CSR_SCSI_DIR | ASIC_CSR_DMAEN_SCSI; 187856819Sralph else 187956819Sralph *ssr = (*ssr & ~ASIC_CSR_SCSI_DIR) | ASIC_CSR_DMAEN_SCSI; 188056819Sralph MachEmptyWriteBuffer(); 188156819Sralph } 188256819Sralph 188356819Sralph static void 188456819Sralph asic_dma_end(asc, state, flag) 188556819Sralph asc_softc_t asc; 188656819Sralph State *state; 188756819Sralph int flag; 188856819Sralph { 188956819Sralph register volatile u_int *ssr = (volatile u_int *) 189057233Sralph ASIC_REG_CSR(asic_base); 189160301Sralph register volatile u_int *dmap = (volatile u_int *) 189260301Sralph ASIC_REG_SCSI_DMAPTR(asic_base); 189360301Sralph register u_short *to; 189460301Sralph register int w; 189556819Sralph int nb; 189656819Sralph 189756819Sralph *ssr &= ~ASIC_CSR_DMAEN_SCSI; 189860301Sralph to = (u_short *)MACH_PHYS_TO_CACHED(*dmap >> 3); 189960301Sralph *dmap = -1; 190057233Sralph *((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1; 190156819Sralph MachEmptyWriteBuffer(); 190256819Sralph 190356819Sralph if (flag == ASCDMA_READ) { 190456819Sralph MachFlushDCache(MACH_PHYS_TO_CACHED( 190556819Sralph MACH_UNCACHED_TO_PHYS(state->dmaBufAddr)), state->dmalen); 190657233Sralph if (nb = *((int *)ASIC_REG_SCSI_SCR(asic_base))) { 190756819Sralph /* pick up last upto6 bytes, sigh. */ 190856819Sralph 190956819Sralph /* Last byte really xferred is.. */ 191057233Sralph w = *(int *)ASIC_REG_SCSI_SDR0(asic_base); 191156819Sralph *to++ = w; 191256819Sralph if (--nb > 0) { 191356819Sralph w >>= 16; 191456819Sralph *to++ = w; 191556819Sralph } 191656819Sralph if (--nb > 0) { 191757233Sralph w = *(int *)ASIC_REG_SCSI_SDR1(asic_base); 191856819Sralph *to++ = w; 191956819Sralph } 192056819Sralph } 192156819Sralph } 192256819Sralph } 192356819Sralph 192457233Sralph #ifdef notdef 192556819Sralph /* 192656819Sralph * Called by asic_intr() for scsi dma pointer update interrupts. 192756819Sralph */ 192856819Sralph void 192956819Sralph asc_dma_intr() 193056819Sralph { 193156819Sralph asc_softc_t asc = &asc_softc[0]; 193256819Sralph u_int next_phys; 193356819Sralph 193456819Sralph asc->dma_xfer -= NBPG; 193556819Sralph if (asc->dma_xfer <= -NBPG) { 193656819Sralph volatile u_int *ssr = (volatile u_int *) 193757233Sralph ASIC_REG_CSR(asic_base); 193856819Sralph *ssr &= ~ASIC_CSR_DMAEN_SCSI; 193956819Sralph } else { 194056819Sralph asc->dma_next += NBPG; 194156819Sralph next_phys = MACH_CACHED_TO_PHYS(asc->dma_next); 194256819Sralph } 194357233Sralph *(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) = 194456819Sralph ASIC_DMA_ADDR(next_phys); 194556819Sralph MachEmptyWriteBuffer(); 194656819Sralph } 194757233Sralph #endif 194856819Sralph 194952889Sbostic #ifdef DEBUG 195052889Sbostic asc_DumpLog(str) 195152889Sbostic char *str; 195252889Sbostic { 195352889Sbostic register struct asc_log *lp; 195452889Sbostic register u_int status; 195552889Sbostic 195652889Sbostic printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd, 195752889Sbostic asc_debug_bn, asc_debug_sz); 195858570Sralph lp = asc_logp; 195958570Sralph do { 196052889Sbostic status = lp->status; 196158658Sralph printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n", 196252889Sbostic status >> 24, 196352889Sbostic lp->target, 196452889Sbostic (status >> 16) & 0xFF, 196552889Sbostic (status >> 8) & 0xFF, 196652889Sbostic status & 0XFF, 196752889Sbostic lp->state, 196852889Sbostic asc_scripts[lp->state].condition, 196958658Sralph lp->msg, lp->resid); 197052889Sbostic if (++lp >= &asc_log[NLOG]) 197152889Sbostic lp = asc_log; 197258570Sralph } while (lp != asc_logp); 197352889Sbostic } 197452889Sbostic #endif 197552889Sbostic 197652889Sbostic #endif /* NASC > 0 */ 1977