// SPDX-License-Identifier: GPL-2.0-or-later /* * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family * of PCI-SCSI IO processors. * * Copyright (C) 1999-2001 Gerard Roudier <[email protected]> * Copyright (c) 2003-2005 Matthew Wilcox <[email protected]> * * This driver is derived from the Linux sym53c8xx driver. * Copyright (C) 1998-2000 Gerard Roudier * * The sym53c8xx driver is derived from the ncr53c8xx driver that had been * a port of the FreeBSD ncr driver to Linux-1.2.13. * * The original ncr driver has been written for 386bsd and FreeBSD by * Wolfgang Stanglmeier <[email protected]> * Stefan Esser <[email protected]> * Copyright (C) 1994 Wolfgang Stanglmeier * * Other major contributions: * * NVRAM detection and reading. * Copyright (C) 1997 Richard Waltham <[email protected]> * *----------------------------------------------------------------------------- */ #include <linux/slab.h> #include <asm/param.h> /* for timeouts in units of HZ */ #include "sym_glue.h" #include "sym_nvram.h" #if 0 #define SYM_DEBUG_GENERIC_SUPPORT #endif /* * Needed function prototypes. */ static void sym_int_ma (struct sym_hcb *np); static void sym_int_sir(struct sym_hcb *); static struct sym_ccb *sym_alloc_ccb(struct sym_hcb *np); static struct sym_ccb *sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa); static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln); static void sym_complete_error (struct sym_hcb *np, struct sym_ccb *cp); static void sym_complete_ok (struct sym_hcb *np, struct sym_ccb *cp); static int sym_compute_residual(struct sym_hcb *np, struct sym_ccb *cp); /* * Print a buffer in hexadecimal format with a ".\n" at end. */ static void sym_printl_hex(u_char *p, int n) { … } static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg) { … } static void sym_print_nego_msg(struct sym_hcb *np, int target, char *label, u_char *msg) { … } /* * Print something that tells about extended errors. */ void sym_print_xerr(struct scsi_cmnd *cmd, int x_status) { … } /* * Return a string for SCSI BUS mode. */ static char *sym_scsi_bus_mode(int mode) { … } /* * Soft reset the chip. * * Raising SRST when the chip is running may cause * problems on dual function chips (see below). * On the other hand, LVD devices need some delay * to settle and report actual BUS mode in STEST4. */ static void sym_chip_reset (struct sym_hcb *np) { … } /* * Really soft reset the chip.:) * * Some 896 and 876 chip revisions may hang-up if we set * the SRST (soft reset) bit at the wrong time when SCRIPTS * are running. * So, we need to abort the current operation prior to * soft resetting the chip. */ static void sym_soft_reset (struct sym_hcb *np) { … } /* * Start reset process. * * The interrupt handler will reinitialize the chip. */ static void sym_start_reset(struct sym_hcb *np) { … } int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int) { … } /* * Select SCSI clock frequency */ static void sym_selectclock(struct sym_hcb *np, u_char scntl3) { … } /* * Determine the chip's clock frequency. * * This is essential for the negotiation of the synchronous * transfer rate. * * Note: we have to return the correct value. * THERE IS NO SAFE DEFAULT VALUE. * * Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock. * 53C860 and 53C875 rev. 1 support fast20 transfers but * do not have a clock doubler and so are provided with a * 80 MHz clock. All other fast20 boards incorporate a doubler * and so should be delivered with a 40 MHz clock. * The recent fast40 chips (895/896/895A/1010) use a 40 Mhz base * clock and provide a clock quadrupler (160 Mhz). */ /* * calculate SCSI clock frequency (in KHz) */ static unsigned getfreq (struct sym_hcb *np, int gen) { … } static unsigned sym_getfreq (struct sym_hcb *np) { … } /* * Get/probe chip SCSI clock frequency */ static void sym_getclock (struct sym_hcb *np, int mult) { … } /* * Get/probe PCI clock frequency */ static int sym_getpciclock (struct sym_hcb *np) { … } /* * SYMBIOS chip clock divisor table. * * Divisors are multiplied by 10,000,000 in order to make * calculations more simple. */ #define _5M … static const u32 div_10M[] = …; /* * Get clock factor and sync divisor for a given * synchronous factor period. */ static int sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fakp) { … } /* * SYMBIOS chips allow burst lengths of 2, 4, 8, 16, 32, 64, * 128 transfers. All chips support at least 16 transfers * bursts. The 825A, 875 and 895 chips support bursts of up * to 128 transfers and the 895A and 896 support bursts of up * to 64 transfers. All other chips support up to 16 * transfers bursts. * * For PCI 32 bit data transfers each transfer is a DWORD. * It is a QUADWORD (8 bytes) for PCI 64 bit data transfers. * * We use log base 2 (burst length) as internal code, with * value 0 meaning "burst disabled". */ /* * Burst length from burst code. */ #define burst_length(bc) … /* * Burst code from io register bits. */ #define burst_code(dmode, ctest4, ctest5) … /* * Set initial io register bits from burst code. */ static inline void sym_init_burst(struct sym_hcb *np, u_char bc) { … } /* * Save initial settings of some IO registers. * Assumed to have been set by BIOS. * We cannot reset the chip prior to reading the * IO registers, since informations will be lost. * Since the SCRIPTS processor may be running, this * is not safe on paper, but it seems to work quite * well. :) */ static void sym_save_initial_setting (struct sym_hcb *np) { … } /* * Set SCSI BUS mode. * - LVD capable chips (895/895A/896/1010) report the current BUS mode * through the STEST4 IO register. * - For previous generation chips (825/825A/875), the user has to tell us * how to check against HVD, since a 100% safe algorithm is not possible. */ static void sym_set_bus_mode(struct sym_hcb *np, struct sym_nvram *nvram) { … } /* * Prepare io register values used by sym_start_up() * according to selected and supported features. */ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram) { … } /* * Test the pci bus snoop logic :-( * * Has to be called with interrupts disabled. */ #ifdef CONFIG_SCSI_SYM53C8XX_MMIO static int sym_regtest(struct sym_hcb *np) { … } #else static inline int sym_regtest(struct sym_hcb *np) { return 0; } #endif static int sym_snooptest(struct sym_hcb *np) { … } /* * log message for real hard errors * * sym0 targ 0?: ERROR (ds:si) (so-si-sd) (sx/s3/s4) @ name (dsp:dbc). * reg: r0 r1 r2 r3 r4 r5 r6 ..... rf. * * exception register: * ds: dstat * si: sist * * SCSI bus lines: * so: control lines as driven by chip. * si: control lines as seen by chip. * sd: scsi data lines as seen by chip. * * wide/fastmode: * sx: sxfer (see the manual) * s3: scntl3 (see the manual) * s4: scntl4 (see the manual) * * current script command: * dsp: script address (relative to start of script). * dbc: first word of script command. * * First 24 register of the chip: * r0..rf */ static void sym_log_hard_error(struct Scsi_Host *shost, u_short sist, u_char dstat) { … } void sym_dump_registers(struct Scsi_Host *shost) { … } static struct sym_chip sym_dev_table[] = …; #define sym_num_devs … /* * Look up the chip table. * * Return a pointer to the chip entry if found, * zero otherwise. */ struct sym_chip * sym_lookup_chip_table (u_short device_id, u_char revision) { … } #if SYM_CONF_DMA_ADDRESSING_MODE == 2 /* * Lookup the 64 bit DMA segments map. * This is only used if the direct mapping * has been unsuccessful. */ int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s) { int i; if (!use_dac(np)) goto weird; /* Look up existing mappings */ for (i = SYM_DMAP_SIZE-1; i > 0; i--) { if (h == np->dmap_bah[i]) return i; } /* If direct mapping is free, get it */ if (!np->dmap_bah[s]) goto new; /* Collision -> lookup free mappings */ for (s = SYM_DMAP_SIZE-1; s > 0; s--) { if (!np->dmap_bah[s]) goto new; } weird: panic("sym: ran out of 64 bit DMA segment registers"); return -1; new: np->dmap_bah[s] = h; np->dmap_dirty = 1; return s; } /* * Update IO registers scratch C..R so they will be * in sync. with queued CCB expectations. */ static void sym_update_dmap_regs(struct sym_hcb *np) { int o, i; if (!np->dmap_dirty) return; o = offsetof(struct sym_reg, nc_scrx[0]); for (i = 0; i < SYM_DMAP_SIZE; i++) { OUTL_OFF(np, o, np->dmap_bah[i]); o += 4; } np->dmap_dirty = 0; } #endif /* Enforce all the fiddly SPI rules and the chip limitations */ static void sym_check_goals(struct sym_hcb *np, struct scsi_target *starget, struct sym_trans *goal) { … } /* * Prepare the next negotiation message if needed. * * Fill in the part of message buffer that contains the * negotiation and the nego_status field of the CCB. * Returns the size of the message in bytes. */ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgptr) { … } /* * Insert a job into the start queue. */ void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp) { … } #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING /* * Start next ready-to-start CCBs. */ void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn) { SYM_QUEHEAD *qp; struct sym_ccb *cp; /* * Paranoia, as usual. :-) */ assert(!lp->started_tags || !lp->started_no_tag); /* * Try to start as many commands as asked by caller. * Prevent from having both tagged and untagged * commands queued to the device at the same time. */ while (maxn--) { qp = sym_remque_head(&lp->waiting_ccbq); if (!qp) break; cp = sym_que_entry(qp, struct sym_ccb, link2_ccbq); if (cp->tag != NO_TAG) { if (lp->started_no_tag || lp->started_tags >= lp->started_max) { sym_insque_head(qp, &lp->waiting_ccbq); break; } lp->itlq_tbl[cp->tag] = cpu_to_scr(cp->ccb_ba); lp->head.resel_sa = cpu_to_scr(SCRIPTA_BA(np, resel_tag)); ++lp->started_tags; } else { if (lp->started_no_tag || lp->started_tags) { sym_insque_head(qp, &lp->waiting_ccbq); break; } lp->head.itl_task_sa = cpu_to_scr(cp->ccb_ba); lp->head.resel_sa = cpu_to_scr(SCRIPTA_BA(np, resel_no_tag)); ++lp->started_no_tag; } cp->started = 1; sym_insque_tail(qp, &lp->started_ccbq); sym_put_start_queue(np, cp); } } #endif /* SYM_OPT_HANDLE_DEVICE_QUEUEING */ /* * The chip may have completed jobs. Look at the DONE QUEUE. * * On paper, memory read barriers may be needed here to * prevent out of order LOADs by the CPU from having * prefetched stale data prior to DMA having occurred. */ static int sym_wakeup_done (struct sym_hcb *np) { … } /* * Complete all CCBs queued to the COMP queue. * * These CCBs are assumed: * - Not to be referenced either by devices or * SCRIPTS-related queues and datas. * - To have to be completed with an error condition * or requeued. * * The device queue freeze count is incremented * for each CCB that does not prevent this. * This function is called when all CCBs involved * in error handling/recovery have been reaped. */ static void sym_flush_comp_queue(struct sym_hcb *np, int cam_status) { … } /* * Complete all active CCBs with error. * Used on CHIP/SCSI RESET. */ static void sym_flush_busy_queue (struct sym_hcb *np, int cam_status) { … } /* * Start chip. * * 'reason' means: * 0: initialisation. * 1: SCSI BUS RESET delivered or received. * 2: SCSI BUS MODE changed. */ void sym_start_up(struct Scsi_Host *shost, int reason) { … } /* * Switch trans mode for current job and its target. */ static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs, u_char per, u_char wide, u_char div, u_char fak) { … } static void sym_announce_transfer_rate(struct sym_tcb *tp) { … } /* * We received a WDTR. * Let everything be aware of the changes. */ static void sym_setwide(struct sym_hcb *np, int target, u_char wide) { … } /* * We received a SDTR. * Let everything be aware of the changes. */ static void sym_setsync(struct sym_hcb *np, int target, u_char ofs, u_char per, u_char div, u_char fak) { … } /* * We received a PPR. * Let everything be aware of the changes. */ static void sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs, u_char per, u_char wide, u_char div, u_char fak) { … } /* * generic recovery from scsi interrupt * * The doc says that when the chip gets an SCSI interrupt, * it tries to stop in an orderly fashion, by completing * an instruction fetch that had started or by flushing * the DMA fifo for a write to memory that was executing. * Such a fashion is not enough to know if the instruction * that was just before the current DSP value has been * executed or not. * * There are some small SCRIPTS sections that deal with * the start queue and the done queue that may break any * assomption from the C code if we are interrupted * inside, so we reset if this happens. Btw, since these * SCRIPTS sections are executed while the SCRIPTS hasn't * started SCSI operations, it is very unlikely to happen. * * All the driver data structures are supposed to be * allocated from the same 4 GB memory window, so there * is a 1 to 1 relationship between DSA and driver data * structures. Since we are careful :) to invalidate the * DSA when we complete a command or when the SCRIPTS * pushes a DSA into a queue, we can trust it when it * points to a CCB. */ static void sym_recover_scsi_int (struct sym_hcb *np, u_char hsts) { … } /* * chip exception handler for selection timeout */ static void sym_int_sto (struct sym_hcb *np) { … } /* * chip exception handler for unexpected disconnect */ static void sym_int_udc (struct sym_hcb *np) { … } /* * chip exception handler for SCSI bus mode change * * spi2-r12 11.2.3 says a transceiver mode change must * generate a reset event and a device that detects a reset * event shall initiate a hard reset. It says also that a * device that detects a mode change shall set data transfer * mode to eight bit asynchronous, etc... * So, just reinitializing all except chip should be enough. */ static void sym_int_sbmc(struct Scsi_Host *shost) { … } /* * chip exception handler for SCSI parity error. * * When the chip detects a SCSI parity error and is * currently executing a (CH)MOV instruction, it does * not interrupt immediately, but tries to finish the * transfer of the current scatter entry before * interrupting. The following situations may occur: * * - The complete scatter entry has been transferred * without the device having changed phase. * The chip will then interrupt with the DSP pointing * to the instruction that follows the MOV. * * - A phase mismatch occurs before the MOV finished * and phase errors are to be handled by the C code. * The chip will then interrupt with both PAR and MA * conditions set. * * - A phase mismatch occurs before the MOV finished and * phase errors are to be handled by SCRIPTS. * The chip will load the DSP with the phase mismatch * JUMP address and interrupt the host processor. */ static void sym_int_par (struct sym_hcb *np, u_short sist) { … } /* * chip exception handler for phase errors. * * We have to construct a new transfer descriptor, * to transfer the rest of the current block. */ static void sym_int_ma (struct sym_hcb *np) { … } /* * chip interrupt handler * * In normal situations, interrupt conditions occur one at * a time. But when something bad happens on the SCSI BUS, * the chip may raise several interrupt flags before * stopping and interrupting the CPU. The additionnal * interrupt flags are stacked in some extra registers * after the SIP and/or DIP flag has been raised in the * ISTAT. After the CPU has read the interrupt condition * flag from SIST or DSTAT, the chip unstacks the other * interrupt flags and sets the corresponding bits in * SIST or DSTAT. Since the chip starts stacking once the * SIP or DIP flag is set, there is a small window of time * where the stacking does not occur. * * Typically, multiple interrupt conditions may happen in * the following situations: * * - SCSI parity error + Phase mismatch (PAR|MA) * When an parity error is detected in input phase * and the device switches to msg-in phase inside a * block MOV. * - SCSI parity error + Unexpected disconnect (PAR|UDC) * When a stupid device does not want to handle the * recovery of an SCSI parity error. * - Some combinations of STO, PAR, UDC, ... * When using non compliant SCSI stuff, when user is * doing non compliant hot tampering on the BUS, when * something really bad happens to a device, etc ... * * The heuristic suggested by SYMBIOS to handle * multiple interrupts is to try unstacking all * interrupts conditions and to handle them on some * priority based on error severity. * This will work when the unstacking has been * successful, but we cannot be 100 % sure of that, * since the CPU may have been faster to unstack than * the chip is able to stack. Hmmm ... But it seems that * such a situation is very unlikely to happen. * * If this happen, for example STO caught by the CPU * then UDC happenning before the CPU have restarted * the SCRIPTS, the driver may wrongly complete the * same command on UDC, since the SCRIPTS didn't restart * and the DSA still points to the same command. * We avoid this situation by setting the DSA to an * invalid value when the CCB is completed and before * restarting the SCRIPTS. * * Another issue is that we need some section of our * recovery procedures to be somehow uninterruptible but * the SCRIPTS processor does not provides such a * feature. For this reason, we handle recovery preferently * from the C code and check against some SCRIPTS critical * sections from the C code. * * Hopefully, the interrupt handling of the driver is now * able to resist to weird BUS error conditions, but donnot * ask me for any guarantee that it will never fail. :-) * Use at your own decision and risk. */ irqreturn_t sym_interrupt(struct Scsi_Host *shost) { … } /* * Dequeue from the START queue all CCBs that match * a given target/lun/task condition (-1 means all), * and move them from the BUSY queue to the COMP queue * with DID_SOFT_ERROR status condition. * This function is used during error handling/recovery. * It is called with SCRIPTS not running. */ static int sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task) { … } /* * chip handler for bad SCSI status condition * * In case of bad SCSI status, we unqueue all the tasks * currently queued to the controller but not yet started * and then restart the SCRIPTS processor immediately. * * QUEUE FULL and BUSY conditions are handled the same way. * Basically all the not yet started tasks are requeued in * device queue and the queue is frozen until a completion. * * For CHECK CONDITION and COMMAND TERMINATED status, we use * the CCB of the failed command to prepare a REQUEST SENSE * SCSI command and queue it to the controller queue. * * SCRATCHA is assumed to have been loaded with STARTPOS * before the SCRIPTS called the C code. */ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, struct sym_ccb *cp) { … } /* * After a device has accepted some management message * as BUS DEVICE RESET, ABORT TASK, etc ..., or when * a device signals a UNIT ATTENTION condition, some * tasks are thrown away by the device. We are required * to reflect that on our tasks list since the device * will never complete these tasks. * * This function move from the BUSY queue to the COMP * queue all disconnected CCBs for a given target that * match the following criteria: * - lun=-1 means any logical UNIT otherwise a given one. * - task=-1 means any task, otherwise a given one. */ int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task) { … } /* * chip handler for TASKS recovery * * We cannot safely abort a command, while the SCRIPTS * processor is running, since we just would be in race * with it. * * As long as we have tasks to abort, we keep the SEM * bit set in the ISTAT. When this bit is set, the * SCRIPTS processor interrupts (SIR_SCRIPT_STOPPED) * each time it enters the scheduler. * * If we have to reset a target, clear tasks of a unit, * or to perform the abort of a disconnected job, we * restart the SCRIPTS for selecting the target. Once * selected, the SCRIPTS interrupts (SIR_TARGET_SELECTED). * If it loses arbitration, the SCRIPTS will interrupt again * the next time it will enter its scheduler, and so on ... * * On SIR_TARGET_SELECTED, we scan for the more * appropriate thing to do: * * - If nothing, we just sent a M_ABORT message to the * target to get rid of the useless SCSI bus ownership. * According to the specs, no tasks shall be affected. * - If the target is to be reset, we send it a M_RESET * message. * - If a logical UNIT is to be cleared , we send the * IDENTIFY(lun) + M_ABORT. * - If an untagged task is to be aborted, we send the * IDENTIFY(lun) + M_ABORT. * - If a tagged task is to be aborted, we send the * IDENTIFY(lun) + task attributes + M_ABORT_TAG. * * Once our 'kiss of death' :) message has been accepted * by the target, the SCRIPTS interrupts again * (SIR_ABORT_SENT). On this interrupt, we complete * all the CCBs that should have been aborted by the * target according to our message. */ static void sym_sir_task_recovery(struct sym_hcb *np, int num) { … } /* * Gerard's alchemy:) that deals with the data * pointer for both MDP and the residual calculation. * * I didn't want to bloat the code by more than 200 * lines for the handling of both MDP and the residual. * This has been achieved by using a data pointer * representation consisting in an index in the data * array (dp_sg) and a negative offset (dp_ofs) that * have the following meaning: * * - dp_sg = SYM_CONF_MAX_SG * we are at the end of the data script. * - dp_sg < SYM_CONF_MAX_SG * dp_sg points to the next entry of the scatter array * we want to transfer. * - dp_ofs < 0 * dp_ofs represents the residual of bytes of the * previous entry scatter entry we will send first. * - dp_ofs = 0 * no residual to send first. * * The function sym_evaluate_dp() accepts an arbitray * offset (basically from the MDP message) and returns * the corresponding values of dp_sg and dp_ofs. */ static int sym_evaluate_dp(struct sym_hcb *np, struct sym_ccb *cp, u32 scr, int *ofs) { … } /* * chip handler for MODIFY DATA POINTER MESSAGE * * We also call this function on IGNORE WIDE RESIDUE * messages that do not match a SWIDE full condition. * Btw, we assume in that situation that such a message * is equivalent to a MODIFY DATA POINTER (offset=-1). */ static void sym_modify_dp(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp, int ofs) { … } /* * chip calculation of the data residual. * * As I used to say, the requirement of data residual * in SCSI is broken, useless and cannot be achieved * without huge complexity. * But most OSes and even the official CAM require it. * When stupidity happens to be so widely spread inside * a community, it gets hard to convince. * * Anyway, I don't care, since I am not going to use * any software that considers this data residual as * a relevant information. :) */ int sym_compute_residual(struct sym_hcb *np, struct sym_ccb *cp) { … } /* * Negotiation for WIDE and SYNCHRONOUS DATA TRANSFER. * * When we try to negotiate, we append the negotiation message * to the identify and (maybe) simple tag message. * The host status field is set to HS_NEGOTIATE to mark this * situation. * * If the target doesn't answer this message immediately * (as required by the standard), the SIR_NEGO_FAILED interrupt * will be raised eventually. * The handler removes the HS_NEGOTIATE status, and sets the * negotiated value to the default (async / nowide). * * If we receive a matching answer immediately, we check it * for validity, and set the values. * * If we receive a Reject message immediately, we assume the * negotiation has failed, and fall back to standard values. * * If we receive a negotiation message while not in HS_NEGOTIATE * state, it's a target initiated negotiation. We prepare a * (hopefully) valid answer, set our parameters, and send back * this answer to the target. * * If the target doesn't fetch the answer (no message out phase), * we assume the negotiation has failed, and fall back to default * settings (SIR_NEGO_PROTO interrupt). * * When we set the values, we adjust them in all ccbs belonging * to this target, in the controller's register, and in the "phys" * field of the controller's struct sym_hcb. */ /* * chip handler for SYNCHRONOUS DATA TRANSFER REQUEST (SDTR) message. */ static int sym_sync_nego_check(struct sym_hcb *np, int req, struct sym_ccb *cp) { … } static void sym_sync_nego(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp) { … } /* * chip handler for PARALLEL PROTOCOL REQUEST (PPR) message. */ static int sym_ppr_nego_check(struct sym_hcb *np, int req, int target) { … } static void sym_ppr_nego(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp) { … } /* * chip handler for WIDE DATA TRANSFER REQUEST (WDTR) message. */ static int sym_wide_nego_check(struct sym_hcb *np, int req, struct sym_ccb *cp) { … } static void sym_wide_nego(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp) { … } /* * Reset DT, SYNC or WIDE to default settings. * * Called when a negotiation does not succeed either * on rejection or on protocol error. * * A target that understands a PPR message should never * reject it, and messing with it is very unlikely. * So, if a PPR makes problems, we may just want to * try a legacy negotiation later. */ static void sym_nego_default(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp) { … } /* * chip handler for MESSAGE REJECT received in response to * PPR, WIDE or SYNCHRONOUS negotiation. */ static void sym_nego_rejected(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp) { … } #define sym_printk(lvl, tp, cp, fmt, v...) … /* * chip exception handler for programmed interrupts. */ static void sym_int_sir(struct sym_hcb *np) { … } /* * Acquire a control block */ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order) { … } /* * Release one control block */ void sym_free_ccb (struct sym_hcb *np, struct sym_ccb *cp) { … } /* * Allocate a CCB from memory and initialize its fixed part. */ static struct sym_ccb *sym_alloc_ccb(struct sym_hcb *np) { … } /* * Look up a CCB from a DSA value. */ static struct sym_ccb *sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa) { … } /* * Target control block initialisation. * Nothing important to do at the moment. */ static void sym_init_tcb (struct sym_hcb *np, u_char tn) { … } /* * Lun control block allocation and initialization. */ struct sym_lcb *sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln) { … } /* * Allocate LCB resources for tagged command queuing. */ static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln) { … } /* * Lun control block deallocation. Returns the number of valid remaining LCBs * for the target. */ int sym_free_lcb(struct sym_hcb *np, u_char tn, u_char ln) { … } /* * Queue a SCSI IO to the controller. */ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp) { … } /* * Reset a SCSI target (all LUNs of this target). */ int sym_reset_scsi_target(struct sym_hcb *np, int target) { … } /* * Abort a SCSI IO. */ static int sym_abort_ccb(struct sym_hcb *np, struct sym_ccb *cp, int timed_out) { … } int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, int timed_out) { … } /* * Complete execution of a SCSI command with extended * error, SCSI status error, or having been auto-sensed. * * The SCRIPTS processor is not running there, so we * can safely access IO registers and remove JOBs from * the START queue. * SCRATCHA is assumed to have been loaded with STARTPOS * before the SCRIPTS called the C code. */ void sym_complete_error(struct sym_hcb *np, struct sym_ccb *cp) { … } /* * Complete execution of a successful SCSI command. * * Only successful commands go to the DONE queue, * since we need to have the SCRIPTS processor * stopped on any error condition. * The SCRIPTS processor is running while we are * completing successful commands. */ void sym_complete_ok (struct sym_hcb *np, struct sym_ccb *cp) { … } /* * Soft-attach the controller. */ int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram *nvram) { … } /* * Free everything that has been allocated for this device. */ void sym_hcb_free(struct sym_hcb *np) { … }