diff -urN oldtree/drivers/scsi/advansys.c newtree/drivers/scsi/advansys.c --- oldtree/drivers/scsi/advansys.c 2006-09-29 14:03:21.000000000 -0400 +++ newtree/drivers/scsi/advansys.c 2006-09-29 16:14:14.000000000 -0400 @@ -798,7 +798,6 @@ #include #include #include -#include "advansys.h" #ifdef CONFIG_PCI #include #endif /* CONFIG_PCI */ @@ -2014,7 +2013,7 @@ STATIC void AscEnableIsaDma(uchar); #endif /* CONFIG_ISA */ STATIC ASC_DCNT AscGetMaxDmaCount(ushort); - +static const char *advansys_info(struct Scsi_Host *shp); /* * --- Adv Library Constants and Macros @@ -3970,10 +3969,6 @@ ASC_IS_PCI, }; -/* - * Used with the LILO 'advansys' option to eliminate or - * limit I/O port probing at boot time, cf. advansys_setup(). - */ STATIC int asc_iopflag = ASC_FALSE; STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 }; @@ -4055,10 +4050,6 @@ #endif /* ADVANSYS_DEBUG */ -/* - * --- Linux 'struct scsi_host_template' and advansys_setup() Functions - */ - #ifdef CONFIG_PROC_FS /* * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] @@ -4080,7 +4071,7 @@ * if 'prtbuf' is too small it will not be overwritten. Instead the * user just won't get all the available statistics. */ -int +static int advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length, int inout) { @@ -4296,7 +4287,7 @@ * it must not call SCSI mid-level functions including scsi_malloc() * and scsi_free(). */ -int __init +static int __init advansys_detect(struct scsi_host_template *tpnt) { static int detect_called = ASC_FALSE; @@ -4403,7 +4394,7 @@ ASC_DBG1(1, "advansys_detect: probing I/O port 0x%x...\n", iop); - if (check_region(iop, ASC_IOADR_GAP) != 0) { + if (!request_region(iop, ASC_IOADR_GAP, "advansys")){ printk( "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop); /* Don't try this I/O port twice. */ @@ -4413,6 +4404,7 @@ printk( "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop); /* Don't try this I/O port twice. */ + release_region(iop, ASC_IOADR_GAP); asc_ioport[ioport] = 0; goto ioport_try_again; } else { @@ -4431,6 +4423,7 @@ * 'ioport' past this board. */ ioport++; + release_region(iop, ASC_IOADR_GAP); goto ioport_try_again; } } @@ -5426,7 +5419,7 @@ * * Release resources allocated for a single AdvanSys adapter. */ -int +static int advansys_release(struct Scsi_Host *shp) { asc_board_t *boardp; @@ -5473,7 +5466,7 @@ * Note: The information line should not exceed ASC_INFO_SIZE bytes, * otherwise the static 'info' array will be overrun. */ -const char * +static const char * advansys_info(struct Scsi_Host *shp) { static char info[ASC_INFO_SIZE]; @@ -5566,7 +5559,7 @@ * This function always returns 0. Command return status is saved * in the 'scp' result field. */ -int +static int advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) { struct Scsi_Host *shp; @@ -5654,7 +5647,7 @@ * sleeping is allowed and no locking other than for host structures is * required. Returns SUCCESS or FAILED. */ -int +static int advansys_reset(struct scsi_cmnd *scp) { struct Scsi_Host *shp; @@ -5839,7 +5832,7 @@ * ip[1]: sectors * ip[2]: cylinders */ -int +static int advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int ip[]) { @@ -5873,82 +5866,6 @@ } /* - * advansys_setup() - * - * This function is called from init/main.c at boot time. - * It it passed LILO parameters that can be set from the - * LILO command line or in /etc/lilo.conf. - * - * It is used by the AdvanSys driver to either disable I/O - * port scanning or to limit scanning to 1 - 4 I/O ports. - * Regardless of the option setting EISA and PCI boards - * will still be searched for and detected. This option - * only affects searching for ISA and VL boards. - * - * If ADVANSYS_DEBUG is defined the driver debug level may - * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. - * - * Examples: - * 1. Eliminate I/O port scanning: - * boot: linux advansys= - * or - * boot: linux advansys=0x0 - * 2. Limit I/O port scanning to one I/O port: - * boot: linux advansys=0x110 - * 3. Limit I/O port scanning to four I/O ports: - * boot: linux advansys=0x110,0x210,0x230,0x330 - * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and - * set the driver debug level to 2. - * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2 - * - * ints[0] - number of arguments - * ints[1] - first argument - * ints[2] - second argument - * ... - */ -void __init -advansys_setup(char *str, int *ints) -{ - int i; - - if (asc_iopflag == ASC_TRUE) { - printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n"); - return; - } - - asc_iopflag = ASC_TRUE; - - if (ints[0] > ASC_NUM_IOPORT_PROBE) { -#ifdef ADVANSYS_DEBUG - if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) && - (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) { - asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf; - } else { -#endif /* ADVANSYS_DEBUG */ - printk("AdvanSys SCSI: only %d I/O ports accepted\n", - ASC_NUM_IOPORT_PROBE); -#ifdef ADVANSYS_DEBUG - } -#endif /* ADVANSYS_DEBUG */ - } - -#ifdef ADVANSYS_DEBUG - ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]); - for (i = 1; i < ints[0]; i++) { - ASC_DBG2(1, " ints[%d] 0x%x", i, ints[i]); - } - ASC_DBG(1, "\n"); -#endif /* ADVANSYS_DEBUG */ - - for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) { - asc_ioport[i-1] = ints[i]; - ASC_DBG2(1, "advansys_setup: asc_ioport[%d] 0x%x\n", - i - 1, asc_ioport[i-1]); - } -} - - -/* * --- Loadable Driver Support */ @@ -9740,13 +9657,14 @@ } for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { iop_base = _asc_def_iop_base[i]; - if (check_region(iop_base, ASC_IOADR_GAP) != 0) { + if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")){ ASC_DBG1(1, "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n", iop_base); continue; } ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n", iop_base); + release_region(iop_base, ASC_IOADR_GAP); if (AscFindSignature(iop_base)) { return (iop_base); } diff -urN oldtree/drivers/scsi/advansys.h newtree/drivers/scsi/advansys.h --- oldtree/drivers/scsi/advansys.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/advansys.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,36 +0,0 @@ -/* - * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters - * - * Copyright (c) 1995-2000 Advanced System Products, Inc. - * Copyright (c) 2000-2001 ConnectCom Solutions, Inc. - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that redistributions of source - * code retain the above copyright notice and this comment without - * modification. - * - * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys) - * changed its name to ConnectCom Solutions, Inc. - * - */ - -#ifndef _ADVANSYS_H -#define _ADVANSYS_H - -/* - * struct scsi_host_template function prototypes. - */ -int advansys_detect(struct scsi_host_template *); -int advansys_release(struct Scsi_Host *); -const char *advansys_info(struct Scsi_Host *); -int advansys_queuecommand(struct scsi_cmnd *, void (* done)(struct scsi_cmnd *)); -int advansys_reset(struct scsi_cmnd *); -int advansys_biosparam(struct scsi_device *, struct block_device *, - sector_t, int[]); -static int advansys_slave_configure(struct scsi_device *); - -/* init/main.c setup function */ -void advansys_setup(char *, int *); - -#endif /* _ADVANSYS_H */ diff -urN oldtree/drivers/scsi/aic7xxx/aic79xx.h newtree/drivers/scsi/aic7xxx/aic79xx.h --- oldtree/drivers/scsi/aic7xxx/aic79xx.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic79xx.h 2006-09-29 16:14:25.000000000 -0400 @@ -972,8 +972,6 @@ int ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf, u_int start_addr, u_int count); -int ahd_wait_seeprom(struct ahd_softc *ahd); -int ahd_verify_vpd_cksum(struct vpd_config *vpd); int ahd_verify_cksum(struct seeprom_config *sc); int ahd_acquire_seeprom(struct ahd_softc *ahd); void ahd_release_seeprom(struct ahd_softc *ahd); @@ -1320,8 +1318,6 @@ char *name; ahd_device_setup_t *setup; }; -extern struct ahd_pci_identity ahd_pci_ident_table []; -extern const u_int ahd_num_pci_devs; /***************************** VL/EISA Declarations ***************************/ struct aic7770_identity { @@ -1338,16 +1334,6 @@ /*************************** Function Declarations ****************************/ /******************************************************************************/ -void ahd_reset_cmds_pending(struct ahd_softc *ahd); -u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl); -void ahd_busy_tcl(struct ahd_softc *ahd, - u_int tcl, u_int busyid); -static __inline void ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl); -static __inline void -ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl) -{ - ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL); -} /***************************** PCI Front End *********************************/ struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t); @@ -1356,12 +1342,8 @@ int ahd_pci_test_register_access(struct ahd_softc *); /************************** SCB and SCB queue management **********************/ -int ahd_probe_scbs(struct ahd_softc *); void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb); -int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, - int target, char channel, int lun, - u_int tag, role_t role); /****************************** Initialization ********************************/ struct ahd_softc *ahd_alloc(void *platform_arg, char *name); @@ -1374,42 +1356,23 @@ int ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc); void ahd_intr_enable(struct ahd_softc *ahd, int enable); -void ahd_update_coalescing_values(struct ahd_softc *ahd, - u_int timer, - u_int maxcmds, - u_int mincmds); -void ahd_enable_coalescing(struct ahd_softc *ahd, - int enable); void ahd_pause_and_flushwork(struct ahd_softc *ahd); int ahd_suspend(struct ahd_softc *ahd); -int ahd_resume(struct ahd_softc *ahd); void ahd_set_unit(struct ahd_softc *, int); void ahd_set_name(struct ahd_softc *, char *); struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); void ahd_free_scb(struct ahd_softc *ahd, struct scb *scb); -void ahd_alloc_scbs(struct ahd_softc *ahd); void ahd_free(struct ahd_softc *ahd); int ahd_reset(struct ahd_softc *ahd, int reinit); -void ahd_shutdown(void *arg); int ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value); int ahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value); -int ahd_wait_flexport(struct ahd_softc *ahd); /*************************** Interrupt Services *******************************/ -void ahd_pci_intr(struct ahd_softc *ahd); -void ahd_clear_intstat(struct ahd_softc *ahd); -void ahd_flush_qoutfifo(struct ahd_softc *ahd); -void ahd_run_qoutfifo(struct ahd_softc *ahd); #ifdef AHD_TARGET_MODE void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused); #endif -void ahd_handle_hwerrint(struct ahd_softc *ahd); -void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat); -void ahd_handle_scsiint(struct ahd_softc *ahd, - u_int intstat); -void ahd_clear_critical_section(struct ahd_softc *ahd); /***************************** Error Recovery *********************************/ typedef enum { @@ -1426,23 +1389,9 @@ char channel, int lun, u_int tag, int stop_on_first, int remove, int save_state); -void ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb); int ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset); -int ahd_abort_scbs(struct ahd_softc *ahd, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status); -void ahd_restart(struct ahd_softc *ahd); -void ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo); -void ahd_handle_scb_status(struct ahd_softc *ahd, - struct scb *scb); -void ahd_handle_scsi_status(struct ahd_softc *ahd, - struct scb *scb); -void ahd_calc_residual(struct ahd_softc *ahd, - struct scb *scb); /*************************** Utility Functions ********************************/ -struct ahd_phase_table_entry* - ahd_lookup_phase_entry(int phase); void ahd_compile_devinfo(struct ahd_devinfo *devinfo, u_int our_id, u_int target, u_int lun, char channel, @@ -1450,14 +1399,6 @@ /************************** Transfer Negotiation ******************************/ void ahd_find_syncrate(struct ahd_softc *ahd, u_int *period, u_int *ppr_options, u_int maxsync); -void ahd_validate_offset(struct ahd_softc *ahd, - struct ahd_initiator_tinfo *tinfo, - u_int period, u_int *offset, - int wide, role_t role); -void ahd_validate_width(struct ahd_softc *ahd, - struct ahd_initiator_tinfo *tinfo, - u_int *bus_width, - role_t role); /* * Negotiation types. These are used to qualify if we should renegotiate * even if our goal and current transport parameters are identical. @@ -1486,11 +1427,6 @@ AHD_QUEUE_TAGGED } ahd_queue_alg; -void ahd_set_tags(struct ahd_softc *ahd, - struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, - ahd_queue_alg alg); - /**************************** Target Mode *************************************/ #ifdef AHD_TARGET_MODE void ahd_send_lstate_events(struct ahd_softc *, @@ -1528,10 +1464,8 @@ #define AHD_SHOW_INT_COALESCING 0x10000 #define AHD_DEBUG_SEQUENCER 0x20000 #endif -void ahd_print_scb(struct scb *scb); void ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); -void ahd_dump_sglist(struct scb *scb); void ahd_dump_card_state(struct ahd_softc *ahd); int ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, @@ -1540,5 +1474,4 @@ u_int value, u_int *cur_column, u_int wrap_point); -void ahd_dump_scbs(struct ahd_softc *ahd); #endif /* _AIC79XX_H_ */ diff -urN oldtree/drivers/scsi/aic7xxx/aic79xx_core.c newtree/drivers/scsi/aic7xxx/aic79xx_core.c --- oldtree/drivers/scsi/aic7xxx/aic79xx_core.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic79xx_core.c 2006-09-29 16:14:25.000000000 -0400 @@ -50,9 +50,614 @@ #include #endif +static void ahd_handle_hwerrint(struct ahd_softc *ahd); +static void ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat); +static void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat); +static void ahd_reset_cmds_pending(struct ahd_softc *ahd); +static void ahd_run_qoutfifo(struct ahd_softc *ahd); + +/***************************** Timer Facilities *******************************/ +#define ahd_timer_init init_timer +#define ahd_timer_stop del_timer_sync +typedef void ahd_linux_callback_t (u_long); +static void +ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) +{ + struct ahd_softc *ahd; + + ahd = (struct ahd_softc *)arg; + del_timer(timer); + timer->data = (u_long)arg; + timer->expires = jiffies + (usec * HZ)/1000000; + timer->function = (ahd_linux_callback_t*)func; + add_timer(timer); +} + +/***************************** Low Level I/O **********************************/ +uint8_t +ahd_inb(struct ahd_softc * ahd, long port) +{ + uint8_t x; + + if (ahd->tags[0] == BUS_SPACE_MEMIO) { + x = readb(ahd->bshs[0].maddr + port); + } else { + x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); + } + mb(); + return (x); +} + +uint16_t +ahd_inw_atomic(struct ahd_softc * ahd, long port) +{ + uint8_t x; + + if (ahd->tags[0] == BUS_SPACE_MEMIO) { + x = readw(ahd->bshs[0].maddr + port); + } else { + x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); + } + mb(); + return (x); +} + +void +ahd_outb(struct ahd_softc * ahd, long port, uint8_t val) +{ + if (ahd->tags[0] == BUS_SPACE_MEMIO) { + writeb(val, ahd->bshs[0].maddr + port); + } else { + outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); + } + mb(); +} + +void +ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val) +{ + if (ahd->tags[0] == BUS_SPACE_MEMIO) { + writew(val, ahd->bshs[0].maddr + port); + } else { + outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); + } + mb(); +} + +static void +ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count) +{ + int i; + + /* + * There is probably a more efficient way to do this on Linux + * but we don't use this for anything speed critical and this + * should work. + */ + for (i = 0; i < count; i++) + ahd_outb(ahd, port, *array++); +} + +#ifdef AHD_DUMP_SEQ +static void +ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count) +{ + int i; + + /* + * There is probably a more efficient way to do this on Linux + * but we don't use this for anything speed critical and this + * should work. + */ + for (i = 0; i < count; i++) + *array++ = ahd_inb(ahd, port); +} +#endif /* AHD_DUMP_SEQ */ + +/************************ Sequencer Execution Control *************************/ +void +ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) +{ + if (ahd->src_mode == src && ahd->dst_mode == dst) + return; +#ifdef AHD_DEBUG + if (ahd->src_mode == AHD_MODE_UNKNOWN + || ahd->dst_mode == AHD_MODE_UNKNOWN) + panic("Setting mode prior to saving it.\n"); + if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) + printf("%s: Setting mode 0x%x\n", ahd_name(ahd), + ahd_build_mode_state(ahd, src, dst)); +#endif + ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst)); + ahd->src_mode = src; + ahd->dst_mode = dst; +} + +static void +ahd_update_modes(struct ahd_softc *ahd) +{ + ahd_mode_state mode_ptr; + ahd_mode src; + ahd_mode dst; + + mode_ptr = ahd_inb(ahd, MODE_PTR); +#ifdef AHD_DEBUG + if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) + printf("Reading mode 0x%x\n", mode_ptr); +#endif + ahd_extract_mode_state(ahd, mode_ptr, &src, &dst); + ahd_known_modes(ahd, src, dst); +} + +ahd_mode_state +ahd_save_modes(struct ahd_softc *ahd) +{ + if (ahd->src_mode == AHD_MODE_UNKNOWN + || ahd->dst_mode == AHD_MODE_UNKNOWN) + ahd_update_modes(ahd); + + return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode)); +} + +void +ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state) +{ + ahd_mode src; + ahd_mode dst; + + ahd_extract_mode_state(ahd, state, &src, &dst); + ahd_set_modes(ahd, src, dst); +} + +/* + * Allow the sequencer to continue program execution. + * We check here to ensure that no additional interrupt + * sources that would cause the sequencer to halt have been + * asserted. If, for example, a SCSI bus reset is detected + * while we are fielding a different, pausing, interrupt type, + * we don't want to release the sequencer before going back + * into our interrupt handler and dealing with this new + * condition. + */ +void +ahd_unpause(struct ahd_softc *ahd) +{ + /* + * Automatically restore our modes to those saved + * prior to the first change of the mode. + */ + if (ahd->saved_src_mode != AHD_MODE_UNKNOWN + && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) { + if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0) + ahd_reset_cmds_pending(ahd); + ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); + } + + if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0) + ahd_outb(ahd, HCNTRL, ahd->unpause); + + ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN); +} + +/*********************** Scatter Gather List Handling *************************/ +void * +ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, + void *sgptr, dma_addr_t addr, bus_size_t len, int last) +{ + scb->sg_count++; + if (sizeof(dma_addr_t) > 4 + && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) { + struct ahd_dma64_seg *sg; + + sg = (struct ahd_dma64_seg *)sgptr; + sg->addr = ahd_htole64(addr); + sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); + return (sg + 1); + } else { + struct ahd_dma_seg *sg; + + sg = (struct ahd_dma_seg *)sgptr; + sg->addr = ahd_htole32(addr & 0xFFFFFFFF); + sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000) + | (last ? AHD_DMA_LAST_SEG : 0)); + return (sg + 1); + } +} + +static void +ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb) +{ + /* XXX Handle target mode SCBs. */ + scb->crc_retry_count = 0; + if ((scb->flags & SCB_PACKETIZED) != 0) { + /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */ + scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE; + } else { + if (ahd_get_transfer_length(scb) & 0x01) + scb->hscb->task_attribute = SCB_XFERLEN_ODD; + else + scb->hscb->task_attribute = 0; + } + + if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR + || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0) + scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr = + ahd_htole32(scb->sense_busaddr); +} + +static void +ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb) +{ + /* + * Copy the first SG into the "current" data ponter area. + */ + if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { + struct ahd_dma64_seg *sg; + + sg = (struct ahd_dma64_seg *)scb->sg_list; + scb->hscb->dataptr = sg->addr; + scb->hscb->datacnt = sg->len; + } else { + struct ahd_dma_seg *sg; + uint32_t *dataptr_words; + + sg = (struct ahd_dma_seg *)scb->sg_list; + dataptr_words = (uint32_t*)&scb->hscb->dataptr; + dataptr_words[0] = sg->addr; + dataptr_words[1] = 0; + if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { + uint64_t high_addr; + + high_addr = ahd_le32toh(sg->len) & 0x7F000000; + scb->hscb->dataptr |= ahd_htole64(high_addr << 8); + } + scb->hscb->datacnt = sg->len; + } + /* + * Note where to find the SG entries in bus space. + * We also set the full residual flag which the + * sequencer will clear as soon as a data transfer + * occurs. + */ + scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID); +} + +/*********************** Miscelaneous Support Functions ***********************/ +uint16_t +ahd_inw(struct ahd_softc *ahd, u_int port) +{ + /* + * Read high byte first as some registers increment + * or have other side effects when the low byte is + * read. + */ + uint16_t r = ahd_inb(ahd, port+1) << 8; + r |= ahd_inb(ahd, port); + return r; +} + +void +ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) +{ + /* + * Write low byte first to accomodate registers + * such as PRGMCNT where the order maters. + */ + ahd_outb(ahd, port, value & 0xFF); + ahd_outb(ahd, port+1, (value >> 8) & 0xFF); +} + +uint32_t +ahd_inl(struct ahd_softc *ahd, u_int port) +{ + return ((ahd_inb(ahd, port)) + | (ahd_inb(ahd, port+1) << 8) + | (ahd_inb(ahd, port+2) << 16) + | (ahd_inb(ahd, port+3) << 24)); +} + +void +ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value) +{ + ahd_outb(ahd, port, (value) & 0xFF); + ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF); + ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF); + ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF); +} + +static uint64_t +ahd_inq(struct ahd_softc *ahd, u_int port) +{ + return ((ahd_inb(ahd, port)) + | (ahd_inb(ahd, port+1) << 8) + | (ahd_inb(ahd, port+2) << 16) + | (ahd_inb(ahd, port+3) << 24) + | (((uint64_t)ahd_inb(ahd, port+4)) << 32) + | (((uint64_t)ahd_inb(ahd, port+5)) << 40) + | (((uint64_t)ahd_inb(ahd, port+6)) << 48) + | (((uint64_t)ahd_inb(ahd, port+7)) << 56)); +} + +static void +ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value) +{ + ahd_outb(ahd, port, value & 0xFF); + ahd_outb(ahd, port+1, (value >> 8) & 0xFF); + ahd_outb(ahd, port+2, (value >> 16) & 0xFF); + ahd_outb(ahd, port+3, (value >> 24) & 0xFF); + ahd_outb(ahd, port+4, (value >> 32) & 0xFF); + ahd_outb(ahd, port+5, (value >> 40) & 0xFF); + ahd_outb(ahd, port+6, (value >> 48) & 0xFF); + ahd_outb(ahd, port+7, (value >> 56) & 0xFF); +} + +u_int +ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) +{ + u_int value; + + /* + * Workaround PCI-X Rev A. hardware bug. + * After a host read of SCB memory, the chip + * may become confused into thinking prefetch + * was required. This starts the discard timer + * running and can cause an unexpected discard + * timer interrupt. The work around is to read + * a normal register prior to the exhaustion of + * the discard timer. The mode pointer register + * has no side effects and so serves well for + * this purpose. + * + * Razor #528 + */ + value = ahd_inb(ahd, offset); + if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0) + ahd_inb(ahd, MODE_PTR); + return (value); +} + +u_int +ahd_inw_scbram(struct ahd_softc *ahd, u_int offset) +{ + return (ahd_inb_scbram(ahd, offset) + | (ahd_inb_scbram(ahd, offset+1) << 8)); +} + +static uint32_t +ahd_inl_scbram(struct ahd_softc *ahd, u_int offset) +{ + return (ahd_inw_scbram(ahd, offset) + | (ahd_inw_scbram(ahd, offset+2) << 16)); +} + +static uint64_t +ahd_inq_scbram(struct ahd_softc *ahd, u_int offset) +{ + return (ahd_inl_scbram(ahd, offset) + | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32); +} + +struct scb * +ahd_lookup_scb(struct ahd_softc *ahd, u_int tag) +{ + struct scb* scb; + + if (tag >= AHD_SCB_MAX) + return (NULL); + scb = ahd->scb_data.scbindex[tag]; + if (scb != NULL) + ahd_sync_scb(ahd, scb, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + return (scb); +} + +static void +ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) +{ + struct hardware_scb *q_hscb; + struct map_node *q_hscb_map; + uint32_t saved_hscb_busaddr; + + /* + * Our queuing method is a bit tricky. The card + * knows in advance which HSCB (by address) to download, + * and we can't disappoint it. To achieve this, the next + * HSCB to download is saved off in ahd->next_queued_hscb. + * When we are called to queue "an arbitrary scb", + * we copy the contents of the incoming HSCB to the one + * the sequencer knows about, swap HSCB pointers and + * finally assign the SCB to the tag indexed location + * in the scb_array. This makes sure that we can still + * locate the correct SCB by SCB_TAG. + */ + q_hscb = ahd->next_queued_hscb; + q_hscb_map = ahd->next_queued_hscb_map; + saved_hscb_busaddr = q_hscb->hscb_busaddr; + memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); + q_hscb->hscb_busaddr = saved_hscb_busaddr; + q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; + + /* Now swap HSCB pointers. */ + ahd->next_queued_hscb = scb->hscb; + ahd->next_queued_hscb_map = scb->hscb_map; + scb->hscb = q_hscb; + scb->hscb_map = q_hscb_map; + + /* Now define the mapping from tag to SCB in the scbindex */ + ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; +} + +/* + * Tell the sequencer about a new transaction to execute. + */ +void +ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb) +{ + ahd_swap_with_next_hscb(ahd, scb); + + if (SCBID_IS_NULL(SCB_GET_TAG(scb))) + panic("Attempt to queue invalid SCB tag %x\n", + SCB_GET_TAG(scb)); + + /* + * Keep a history of SCBs we've downloaded in the qinfifo. + */ + ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb); + ahd->qinfifonext++; + + if (scb->sg_count != 0) + ahd_setup_data_scb(ahd, scb); + else + ahd_setup_noxfer_scb(ahd, scb); + ahd_setup_scb_common(ahd, scb); + + /* + * Make sure our data is consistent from the + * perspective of the adapter. + */ + ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + +#ifdef AHD_DEBUG + if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { + uint64_t host_dataptr; + + host_dataptr = ahd_le64toh(scb->hscb->dataptr); + printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n", + ahd_name(ahd), + SCB_GET_TAG(scb), scb->hscb->scsiid, + ahd_le32toh(scb->hscb->hscb_busaddr), + (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), + (u_int)(host_dataptr & 0xFFFFFFFF), + ahd_le32toh(scb->hscb->datacnt)); + } +#endif + /* Tell the adapter about the newly queued SCB */ + ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); +} + +/************************** Interrupt Processing ******************************/ +/* + * See if the firmware has posted any completed commands + * into our in-core command complete fifos. + */ +#define AHD_RUN_QOUTFIFO 0x1 +#define AHD_RUN_TQINFIFO 0x2 +static u_int +ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) +{ + u_int retval; + + retval = 0; + ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo), + /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD); + if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag + == ahd->qoutfifonext_valid_tag) + retval |= AHD_RUN_QOUTFIFO; +#ifdef AHD_TARGET_MODE + if ((ahd->flags & AHD_TARGETROLE) != 0 + && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { + ahd_dmamap_sync(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap, + ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), + /*len*/sizeof(struct target_cmd), + BUS_DMASYNC_POSTREAD); + if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0) + retval |= AHD_RUN_TQINFIFO; + } +#endif + return (retval); +} + +/* + * Catch an interrupt from the adapter + */ +int +ahd_intr(struct ahd_softc *ahd) +{ + u_int intstat; + + if ((ahd->pause & INTEN) == 0) { + /* + * Our interrupt is not enabled on the chip + * and may be disabled for re-entrancy reasons, + * so just return. This is likely just a shared + * interrupt. + */ + return (0); + } + + /* + * Instead of directly reading the interrupt status register, + * infer the cause of the interrupt by checking our in-core + * completion queues. This avoids a costly PCI bus read in + * most cases. + */ + if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0 + && (ahd_check_cmdcmpltqueues(ahd) != 0)) + intstat = CMDCMPLT; + else + intstat = ahd_inb(ahd, INTSTAT); + + if ((intstat & INT_PEND) == 0) + return (0); + + if (intstat & CMDCMPLT) { + ahd_outb(ahd, CLRINT, CLRCMDINT); + + /* + * Ensure that the chip sees that we've cleared + * this interrupt before we walk the output fifo. + * Otherwise, we may, due to posted bus writes, + * clear the interrupt after we finish the scan, + * and after the sequencer has added new entries + * and asserted the interrupt again. + */ + if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { + if (ahd_is_paused(ahd)) { + /* + * Potentially lost SEQINT. + * If SEQINTCODE is non-zero, + * simulate the SEQINT. + */ + if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT) + intstat |= SEQINT; + } + } else { + ahd_flush_device_writes(ahd); + } + ahd_run_qoutfifo(ahd); + ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++; + ahd->cmdcmplt_total++; +#ifdef AHD_TARGET_MODE + if ((ahd->flags & AHD_TARGETROLE) != 0) + ahd_run_tqinfifo(ahd, /*paused*/FALSE); +#endif + } + + /* + * Handle statuses that may invalidate our cached + * copy of INTSTAT separately. + */ + if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) { + /* Hot eject. Do nothing */ + } else if (intstat & HWERRINT) { + ahd_handle_hwerrint(ahd); + } else if ((intstat & (PCIINT|SPLTINT)) != 0) { + ahd->bus_intr(ahd); + } else { + + if ((intstat & SEQINT) != 0) + ahd_handle_seqint(ahd, intstat); + + if ((intstat & SCSIINT) != 0) + ahd_handle_scsiint(ahd, intstat); + } + return (1); +} /***************************** Lookup Tables **********************************/ -char *ahd_chip_names[] = +static char *ahd_chip_names[] = { "NONE", "aic7901", @@ -237,12 +842,38 @@ struct target_cmd *cmd); #endif +static int ahd_abort_scbs(struct ahd_softc *ahd, int target, + char channel, int lun, u_int tag, + role_t role, uint32_t status); +static void ahd_alloc_scbs(struct ahd_softc *ahd); +static void ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, + u_int scbid); +static void ahd_calc_residual(struct ahd_softc *ahd, + struct scb *scb); +static void ahd_clear_critical_section(struct ahd_softc *ahd); +static void ahd_clear_intstat(struct ahd_softc *ahd); +static void ahd_enable_coalescing(struct ahd_softc *ahd, + int enable); +static u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl); +static void ahd_freeze_devq(struct ahd_softc *ahd, + struct scb *scb); +static void ahd_handle_scb_status(struct ahd_softc *ahd, + struct scb *scb); +static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase); +static void ahd_shutdown(void *arg); +static void ahd_update_coalescing_values(struct ahd_softc *ahd, + u_int timer, + u_int maxcmds, + u_int mincmds); +static int ahd_verify_vpd_cksum(struct vpd_config *vpd); +static int ahd_wait_seeprom(struct ahd_softc *ahd); +static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, + int target, char channel, int lun, + u_int tag, role_t role); + /******************************** Private Inlines *****************************/ -static __inline void ahd_assert_atn(struct ahd_softc *ahd); -static __inline int ahd_currently_packetized(struct ahd_softc *ahd); -static __inline int ahd_set_active_fifo(struct ahd_softc *ahd); -static __inline void +static inline void ahd_assert_atn(struct ahd_softc *ahd) { ahd_outb(ahd, SCSISIGO, ATNO); @@ -254,7 +885,7 @@ * are currently in a packetized transfer. We could * just as easily be sending or receiving a message. */ -static __inline int +static inline int ahd_currently_packetized(struct ahd_softc *ahd) { ahd_mode_state saved_modes; @@ -277,7 +908,7 @@ return (packetized); } -static __inline int +static int ahd_set_active_fifo(struct ahd_softc *ahd) { u_int active_fifo; @@ -294,11 +925,44 @@ } } +static inline void +ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl) +{ + ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL); +} + +/* + * Determine whether the sequencer reported a residual + * for this SCB/transaction. + */ +static inline void +ahd_update_residual(struct ahd_softc *ahd, struct scb *scb) +{ + uint32_t sgptr; + + sgptr = ahd_le32toh(scb->hscb->sgptr); + if ((sgptr & SG_STATUS_VALID) != 0) + ahd_calc_residual(ahd, scb); +} + +static inline void +ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) +{ + uint32_t sgptr; + + sgptr = ahd_le32toh(scb->hscb->sgptr); + if ((sgptr & SG_STATUS_VALID) != 0) + ahd_handle_scb_status(ahd, scb); + else + ahd_done(ahd, scb); +} + + /************************* Sequencer Execution Control ************************/ /* * Restart the sequencer program from address zero */ -void +static void ahd_restart(struct ahd_softc *ahd) { @@ -342,7 +1006,7 @@ ahd_unpause(ahd); } -void +static void ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo) { ahd_mode_state saved_modes; @@ -366,7 +1030,7 @@ * Flush and completed commands that are sitting in the command * complete queues down on the chip but have yet to be dma'ed back up. */ -void +static void ahd_flush_qoutfifo(struct ahd_softc *ahd) { struct scb *scb; @@ -837,7 +1501,7 @@ * a copy of the first byte (little endian) of the sgptr * hscb field. */ -void +static void ahd_run_qoutfifo(struct ahd_softc *ahd) { struct ahd_completion *completion; @@ -876,7 +1540,7 @@ } /************************* Interrupt Handling *********************************/ -void +static void ahd_handle_hwerrint(struct ahd_softc *ahd) { /* @@ -905,7 +1569,52 @@ ahd_free(ahd); } -void +#ifdef AHD_DEBUG +static void +ahd_dump_sglist(struct scb *scb) +{ + int i; + + if (scb->sg_count > 0) { + if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) { + struct ahd_dma64_seg *sg_list; + + sg_list = (struct ahd_dma64_seg*)scb->sg_list; + for (i = 0; i < scb->sg_count; i++) { + uint64_t addr; + uint32_t len; + + addr = ahd_le64toh(sg_list[i].addr); + len = ahd_le32toh(sg_list[i].len); + printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", + i, + (uint32_t)((addr >> 32) & 0xFFFFFFFF), + (uint32_t)(addr & 0xFFFFFFFF), + sg_list[i].len & AHD_SG_LEN_MASK, + (sg_list[i].len & AHD_DMA_LAST_SEG) + ? " Last" : ""); + } + } else { + struct ahd_dma_seg *sg_list; + + sg_list = (struct ahd_dma_seg*)scb->sg_list; + for (i = 0; i < scb->sg_count; i++) { + uint32_t len; + + len = ahd_le32toh(sg_list[i].len); + printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", + i, + (len & AHD_SG_HIGH_ADDR_MASK) >> 24, + ahd_le32toh(sg_list[i].addr), + len & AHD_SG_LEN_MASK, + len & AHD_DMA_LAST_SEG ? " Last" : ""); + } + } + } +} +#endif /* AHD_DEBUG */ + +static void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) { u_int seqintcode; @@ -1494,7 +2203,7 @@ ahd_unpause(ahd); } -void +static void ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) { struct scb *scb; @@ -2523,7 +3232,7 @@ } #define AHD_MAX_STEPS 2000 -void +static void ahd_clear_critical_section(struct ahd_softc *ahd) { ahd_mode_state saved_modes; @@ -2646,7 +3355,7 @@ /* * Clear any pending interrupt status. */ -void +static void ahd_clear_intstat(struct ahd_softc *ahd) { AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), @@ -2677,6 +3386,8 @@ #ifdef AHD_DEBUG uint32_t ahd_debug = AHD_DEBUG_OPTS; #endif + +#if 0 void ahd_print_scb(struct scb *scb) { @@ -2701,49 +3412,7 @@ SCB_GET_TAG(scb)); ahd_dump_sglist(scb); } - -void -ahd_dump_sglist(struct scb *scb) -{ - int i; - - if (scb->sg_count > 0) { - if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg_list; - - sg_list = (struct ahd_dma64_seg*)scb->sg_list; - for (i = 0; i < scb->sg_count; i++) { - uint64_t addr; - uint32_t len; - - addr = ahd_le64toh(sg_list[i].addr); - len = ahd_le32toh(sg_list[i].len); - printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", - i, - (uint32_t)((addr >> 32) & 0xFFFFFFFF), - (uint32_t)(addr & 0xFFFFFFFF), - sg_list[i].len & AHD_SG_LEN_MASK, - (sg_list[i].len & AHD_DMA_LAST_SEG) - ? " Last" : ""); - } - } else { - struct ahd_dma_seg *sg_list; - - sg_list = (struct ahd_dma_seg*)scb->sg_list; - for (i = 0; i < scb->sg_count; i++) { - uint32_t len; - - len = ahd_le32toh(sg_list[i].len); - printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", - i, - (len & AHD_SG_HIGH_ADDR_MASK) >> 24, - ahd_le32toh(sg_list[i].addr), - len & AHD_SG_LEN_MASK, - len & AHD_DMA_LAST_SEG ? " Last" : ""); - } - } - } -} +#endif /* 0 */ /************************* Transfer Negotiation *******************************/ /* @@ -2906,7 +3575,7 @@ * Truncate the given synchronous offset to a value the * current adapter type and syncrate are capable of. */ -void +static void ahd_validate_offset(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, u_int period, u_int *offset, int wide, @@ -2937,7 +3606,7 @@ * Truncate the given transfer width parameter to a value the * current adapter type is capable of. */ -void +static void ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, u_int *bus_width, role_t role) { @@ -3210,7 +3879,7 @@ /* * Update the current state of tagged queuing for a given target. */ -void +static void ahd_set_tags(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, ahd_queue_alg alg) { @@ -3466,7 +4135,7 @@ devinfo->target, devinfo->lun); } -struct ahd_phase_table_entry* +static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase) { struct ahd_phase_table_entry *entry; @@ -5351,7 +6020,7 @@ return; } -void +static void ahd_shutdown(void *arg) { struct ahd_softc *ahd; @@ -5480,7 +6149,7 @@ /* * Determine the number of SCBs available on the controller */ -int +static int ahd_probe_scbs(struct ahd_softc *ahd) { int i; @@ -5929,7 +6598,7 @@ ahd_platform_scb_free(ahd, scb); } -void +static void ahd_alloc_scbs(struct ahd_softc *ahd) { struct scb_data *scb_data; @@ -6982,7 +7651,7 @@ ahd_outb(ahd, HCNTRL, hcntrl); } -void +static void ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds, u_int mincmds) { @@ -7000,7 +7669,7 @@ ahd_outb(ahd, INT_COALESCING_MINCMDS, -mincmds); } -void +static void ahd_enable_coalescing(struct ahd_softc *ahd, int enable) { @@ -7070,6 +7739,7 @@ ahd->flags &= ~AHD_ALL_INTERRUPTS; } +#if 0 int ahd_suspend(struct ahd_softc *ahd) { @@ -7083,7 +7753,9 @@ ahd_shutdown(ahd); return (0); } +#endif /* 0 */ +#if 0 int ahd_resume(struct ahd_softc *ahd) { @@ -7093,6 +7765,7 @@ ahd_restart(ahd); return (0); } +#endif /* 0 */ /************************** Busy Target Table *********************************/ /* @@ -7103,7 +7776,7 @@ * scbid that should be restored once manipualtion * of the TCL entry is complete. */ -static __inline u_int +static u_int ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl) { /* @@ -7125,7 +7798,7 @@ /* * Return the untagged transaction id for a given target/channel lun. */ -u_int +static u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl) { u_int scbid; @@ -7138,7 +7811,7 @@ return (scbid); } -void +static void ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid) { u_int scb_offset; @@ -7150,7 +7823,7 @@ } /************************** SCB and SCB queue management **********************/ -int +static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target, char channel, int lun, u_int tag, role_t role) { @@ -7186,7 +7859,7 @@ return match; } -void +static void ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb) { int target; @@ -7264,7 +7937,7 @@ + ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos); } -void +static void ahd_reset_cmds_pending(struct ahd_softc *ahd) { struct scb *scb; @@ -7690,7 +8363,7 @@ * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer * is paused before it is called. */ -int +static int ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status) { @@ -8019,18 +8692,8 @@ } /****************************** Status Processing *****************************/ -void -ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) -{ - if (scb->hscb->shared_data.istatus.scsi_status != 0) { - ahd_handle_scsi_status(ahd, scb); - } else { - ahd_calc_residual(ahd, scb); - ahd_done(ahd, scb); - } -} -void +static void ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) { struct hardware_scb *hscb; @@ -8229,7 +8892,7 @@ break; } case SCSI_STATUS_OK: - printf("%s: Interrupted for staus of 0???\n", + printf("%s: Interrupted for status of 0???\n", ahd_name(ahd)); /* FALLTHROUGH */ default: @@ -8238,10 +8901,21 @@ } } +static void +ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) +{ + if (scb->hscb->shared_data.istatus.scsi_status != 0) { + ahd_handle_scsi_status(ahd, scb); + } else { + ahd_calc_residual(ahd, scb); + ahd_done(ahd, scb); + } +} + /* * Calculate the residual for a just completed SCB. */ -void +static void ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) { struct hardware_scb *hscb; @@ -9092,6 +9766,7 @@ ahd_unpause(ahd); } +#if 0 void ahd_dump_scbs(struct ahd_softc *ahd) { @@ -9117,6 +9792,7 @@ ahd_set_scbptr(ahd, saved_scb_index); ahd_restore_modes(ahd, saved_modes); } +#endif /* 0 */ /**************************** Flexport Logic **********************************/ /* @@ -9219,7 +9895,7 @@ /* * Wait ~100us for the serial eeprom to satisfy our request. */ -int +static int ahd_wait_seeprom(struct ahd_softc *ahd) { int cnt; @@ -9237,7 +9913,7 @@ * Validate the two checksums in the per_channel * vital product data struct. */ -int +static int ahd_verify_vpd_cksum(struct vpd_config *vpd) { int i; @@ -9316,6 +9992,24 @@ /* Currently a no-op */ } +/* + * Wait at most 2 seconds for flexport arbitration to succeed. + */ +static int +ahd_wait_flexport(struct ahd_softc *ahd) +{ + int cnt; + + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); + cnt = 1000000 * 2 / 5; + while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) + ahd_delay(5); + + if (cnt == 0) + return (ETIMEDOUT); + return (0); +} + int ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value) { @@ -9357,24 +10051,6 @@ return (0); } -/* - * Wait at most 2 seconds for flexport arbitration to succeed. - */ -int -ahd_wait_flexport(struct ahd_softc *ahd) -{ - int cnt; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - cnt = 1000000 * 2 / 5; - while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) - ahd_delay(5); - - if (cnt == 0) - return (ETIMEDOUT); - return (0); -} - /************************* Target Mode ****************************************/ #ifdef AHD_TARGET_MODE cam_status diff -urN oldtree/drivers/scsi/aic7xxx/aic79xx_inline.h newtree/drivers/scsi/aic7xxx/aic79xx_inline.h --- oldtree/drivers/scsi/aic7xxx/aic79xx_inline.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic79xx_inline.h 2006-09-29 16:13:56.000000000 -0400 @@ -46,37 +46,36 @@ #define _AIC79XX_INLINE_H_ /******************************** Debugging ***********************************/ -static __inline char *ahd_name(struct ahd_softc *ahd); +static inline char *ahd_name(struct ahd_softc *ahd); -static __inline char * +static inline char * ahd_name(struct ahd_softc *ahd) { return (ahd->name); } /************************ Sequencer Execution Control *************************/ -static __inline void ahd_known_modes(struct ahd_softc *ahd, +static inline void ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst); -static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd, +static inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst); -static __inline void ahd_extract_mode_state(struct ahd_softc *ahd, +static inline void ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state, ahd_mode *src, ahd_mode *dst); -static __inline void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, +void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst); -static __inline void ahd_update_modes(struct ahd_softc *ahd); -static __inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode, +static inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode, ahd_mode dstmode, const char *file, int line); -static __inline ahd_mode_state ahd_save_modes(struct ahd_softc *ahd); -static __inline void ahd_restore_modes(struct ahd_softc *ahd, +ahd_mode_state ahd_save_modes(struct ahd_softc *ahd); +void ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state); -static __inline int ahd_is_paused(struct ahd_softc *ahd); -static __inline void ahd_pause(struct ahd_softc *ahd); -static __inline void ahd_unpause(struct ahd_softc *ahd); +static inline int ahd_is_paused(struct ahd_softc *ahd); +static inline void ahd_pause(struct ahd_softc *ahd); +void ahd_unpause(struct ahd_softc *ahd); -static __inline void +static inline void ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) { ahd->src_mode = src; @@ -85,13 +84,13 @@ ahd->saved_dst_mode = dst; } -static __inline ahd_mode_state +static inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) { return ((src << SRC_MODE_SHIFT) | (dst << DST_MODE_SHIFT)); } -static __inline void +static inline void ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state, ahd_mode *src, ahd_mode *dst) { @@ -99,41 +98,7 @@ *dst = (state & DST_MODE) >> DST_MODE_SHIFT; } -static __inline void -ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) -{ - if (ahd->src_mode == src && ahd->dst_mode == dst) - return; -#ifdef AHD_DEBUG - if (ahd->src_mode == AHD_MODE_UNKNOWN - || ahd->dst_mode == AHD_MODE_UNKNOWN) - panic("Setting mode prior to saving it.\n"); - if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) - printf("%s: Setting mode 0x%x\n", ahd_name(ahd), - ahd_build_mode_state(ahd, src, dst)); -#endif - ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst)); - ahd->src_mode = src; - ahd->dst_mode = dst; -} - -static __inline void -ahd_update_modes(struct ahd_softc *ahd) -{ - ahd_mode_state mode_ptr; - ahd_mode src; - ahd_mode dst; - - mode_ptr = ahd_inb(ahd, MODE_PTR); -#ifdef AHD_DEBUG - if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) - printf("Reading mode 0x%x\n", mode_ptr); -#endif - ahd_extract_mode_state(ahd, mode_ptr, &src, &dst); - ahd_known_modes(ahd, src, dst); -} - -static __inline void +static inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode, ahd_mode dstmode, const char *file, int line) { @@ -146,26 +111,6 @@ #endif } -static __inline ahd_mode_state -ahd_save_modes(struct ahd_softc *ahd) -{ - if (ahd->src_mode == AHD_MODE_UNKNOWN - || ahd->dst_mode == AHD_MODE_UNKNOWN) - ahd_update_modes(ahd); - - return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode)); -} - -static __inline void -ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state) -{ - ahd_mode src; - ahd_mode dst; - - ahd_extract_mode_state(ahd, state, &src, &dst); - ahd_set_modes(ahd, src, dst); -} - #define AHD_ASSERT_MODES(ahd, source, dest) \ ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__); @@ -173,7 +118,7 @@ * Determine whether the sequencer has halted code execution. * Returns non-zero status if the sequencer is stopped. */ -static __inline int +static inline int ahd_is_paused(struct ahd_softc *ahd) { return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0); @@ -186,7 +131,7 @@ * cleared in the SEQCTL register. The sequencer may use PAUSEDIS * for critical sections. */ -static __inline void +static inline void ahd_pause(struct ahd_softc *ahd) { ahd_outb(ahd, HCNTRL, ahd->pause); @@ -199,130 +144,14 @@ ; } -/* - * Allow the sequencer to continue program execution. - * We check here to ensure that no additional interrupt - * sources that would cause the sequencer to halt have been - * asserted. If, for example, a SCSI bus reset is detected - * while we are fielding a different, pausing, interrupt type, - * we don't want to release the sequencer before going back - * into our interrupt handler and dealing with this new - * condition. - */ -static __inline void -ahd_unpause(struct ahd_softc *ahd) -{ - /* - * Automatically restore our modes to those saved - * prior to the first change of the mode. - */ - if (ahd->saved_src_mode != AHD_MODE_UNKNOWN - && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) { - if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0) - ahd_reset_cmds_pending(ahd); - ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); - } - - if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0) - ahd_outb(ahd, HCNTRL, ahd->unpause); - - ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN); -} - /*********************** Scatter Gather List Handling *************************/ -static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, +void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, void *sgptr, dma_addr_t addr, bus_size_t len, int last); -static __inline void ahd_setup_scb_common(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_setup_data_scb(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd, +static inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb); -static __inline void * -ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, - void *sgptr, dma_addr_t addr, bus_size_t len, int last) -{ - scb->sg_count++; - if (sizeof(dma_addr_t) > 4 - && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg; - - sg = (struct ahd_dma64_seg *)sgptr; - sg->addr = ahd_htole64(addr); - sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); - return (sg + 1); - } else { - struct ahd_dma_seg *sg; - - sg = (struct ahd_dma_seg *)sgptr; - sg->addr = ahd_htole32(addr & 0xFFFFFFFF); - sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000) - | (last ? AHD_DMA_LAST_SEG : 0)); - return (sg + 1); - } -} - -static __inline void -ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb) -{ - /* XXX Handle target mode SCBs. */ - scb->crc_retry_count = 0; - if ((scb->flags & SCB_PACKETIZED) != 0) { - /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */ - scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE; - } else { - if (ahd_get_transfer_length(scb) & 0x01) - scb->hscb->task_attribute = SCB_XFERLEN_ODD; - else - scb->hscb->task_attribute = 0; - } - - if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR - || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0) - scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr = - ahd_htole32(scb->sense_busaddr); -} - -static __inline void -ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb) -{ - /* - * Copy the first SG into the "current" data ponter area. - */ - if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg; - - sg = (struct ahd_dma64_seg *)scb->sg_list; - scb->hscb->dataptr = sg->addr; - scb->hscb->datacnt = sg->len; - } else { - struct ahd_dma_seg *sg; - uint32_t *dataptr_words; - - sg = (struct ahd_dma_seg *)scb->sg_list; - dataptr_words = (uint32_t*)&scb->hscb->dataptr; - dataptr_words[0] = sg->addr; - dataptr_words[1] = 0; - if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { - uint64_t high_addr; - - high_addr = ahd_le32toh(sg->len) & 0x7F000000; - scb->hscb->dataptr |= ahd_htole64(high_addr << 8); - } - scb->hscb->datacnt = sg->len; - } - /* - * Note where to find the SG entries in bus space. - * We also set the full residual flag which the - * sequencer will clear as soon as a data transfer - * occurs. - */ - scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID); -} - -static __inline void +static inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb) { scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL); @@ -331,26 +160,26 @@ } /************************** Memory mapping routines ***************************/ -static __inline size_t ahd_sg_size(struct ahd_softc *ahd); -static __inline void * +static inline size_t ahd_sg_size(struct ahd_softc *ahd); +static inline void * ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr); -static __inline uint32_t +static inline uint32_t ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg); -static __inline void ahd_sync_scb(struct ahd_softc *ahd, +static inline void ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op); -static __inline void ahd_sync_sglist(struct ahd_softc *ahd, +static inline void ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op); -static __inline void ahd_sync_sense(struct ahd_softc *ahd, +static inline void ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op); -static __inline uint32_t +static inline uint32_t ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index); -static __inline size_t +static inline size_t ahd_sg_size(struct ahd_softc *ahd) { if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) @@ -358,7 +187,7 @@ return (sizeof(struct ahd_dma_seg)); } -static __inline void * +static inline void * ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr) { dma_addr_t sg_offset; @@ -368,7 +197,7 @@ return ((uint8_t *)scb->sg_list + sg_offset); } -static __inline uint32_t +static inline uint32_t ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg) { dma_addr_t sg_offset; @@ -380,7 +209,7 @@ return (scb->sg_list_busaddr + sg_offset); } -static __inline void +static inline void ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op) { ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, @@ -389,7 +218,7 @@ /*len*/sizeof(*scb->hscb), op); } -static __inline void +static inline void ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op) { if (scb->sg_count == 0) @@ -401,7 +230,7 @@ /*len*/ahd_sg_size(ahd) * scb->sg_count, op); } -static __inline void +static inline void ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op) { ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat, @@ -410,7 +239,7 @@ /*len*/AHD_SENSE_BUFSIZE, op); } -static __inline uint32_t +static inline uint32_t ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index) { return (((uint8_t *)&ahd->targetcmds[index]) @@ -418,86 +247,43 @@ } /*********************** Miscelaneous Support Functions ***********************/ -static __inline void ahd_complete_scb(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_update_residual(struct ahd_softc *ahd, - struct scb *scb); -static __inline struct ahd_initiator_tinfo * +static inline struct ahd_initiator_tinfo * ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id, u_int remote_id, struct ahd_tmode_tstate **tstate); -static __inline uint16_t - ahd_inw(struct ahd_softc *ahd, u_int port); -static __inline void ahd_outw(struct ahd_softc *ahd, u_int port, - u_int value); -static __inline uint32_t - ahd_inl(struct ahd_softc *ahd, u_int port); -static __inline void ahd_outl(struct ahd_softc *ahd, u_int port, - uint32_t value); -static __inline uint64_t - ahd_inq(struct ahd_softc *ahd, u_int port); -static __inline void ahd_outq(struct ahd_softc *ahd, u_int port, - uint64_t value); -static __inline u_int ahd_get_scbptr(struct ahd_softc *ahd); -static __inline void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr); -static __inline u_int ahd_get_hnscb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_get_hescb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_get_snscb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_get_sescb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_get_sdscb_qoff(struct ahd_softc *ahd); -static __inline void ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value); -static __inline u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset); -static __inline u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset); -static __inline uint32_t - ahd_inl_scbram(struct ahd_softc *ahd, u_int offset); -static __inline uint64_t - ahd_inq_scbram(struct ahd_softc *ahd, u_int offset); -static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb); -static __inline uint8_t * +uint16_t ahd_inw(struct ahd_softc *ahd, u_int port); +void ahd_outw(struct ahd_softc *ahd, u_int port, u_int value); +uint32_t ahd_inl(struct ahd_softc *ahd, u_int port); +void ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value); +static inline u_int ahd_get_scbptr(struct ahd_softc *ahd); +static inline void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr); +static inline u_int ahd_get_hnscb_qoff(struct ahd_softc *ahd); +static inline void ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value); +static inline u_int ahd_get_hescb_qoff(struct ahd_softc *ahd); +static inline void ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value); +static inline u_int ahd_get_snscb_qoff(struct ahd_softc *ahd); +static inline void ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value); +static inline u_int ahd_get_sescb_qoff(struct ahd_softc *ahd); +static inline void ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value); +static inline u_int ahd_get_sdscb_qoff(struct ahd_softc *ahd); +static inline void ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value); +u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset); +u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset); +struct scb *ahd_lookup_scb(struct ahd_softc *ahd, u_int tag); +void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb); +static inline uint8_t * ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb); -static __inline uint32_t +static inline uint32_t ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb); -static __inline void -ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) -{ - uint32_t sgptr; - - sgptr = ahd_le32toh(scb->hscb->sgptr); - if ((sgptr & SG_STATUS_VALID) != 0) - ahd_handle_scb_status(ahd, scb); - else - ahd_done(ahd, scb); -} - -/* - * Determine whether the sequencer reported a residual - * for this SCB/transaction. - */ -static __inline void -ahd_update_residual(struct ahd_softc *ahd, struct scb *scb) -{ - uint32_t sgptr; - - sgptr = ahd_le32toh(scb->hscb->sgptr); - if ((sgptr & SG_STATUS_VALID) != 0) - ahd_calc_residual(ahd, scb); -} - /* * Return pointers to the transfer negotiation information * for the specified our_id/remote_id pair. */ -static __inline struct ahd_initiator_tinfo * +static inline struct ahd_initiator_tinfo * ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id, u_int remote_id, struct ahd_tmode_tstate **tstate) { @@ -519,73 +305,7 @@ dst->hscb->lun = src->hscb->lun; \ } while (0) -static __inline uint16_t -ahd_inw(struct ahd_softc *ahd, u_int port) -{ - /* - * Read high byte first as some registers increment - * or have other side effects when the low byte is - * read. - */ - return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port)); -} - -static __inline void -ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) -{ - /* - * Write low byte first to accomodate registers - * such as PRGMCNT where the order maters. - */ - ahd_outb(ahd, port, value & 0xFF); - ahd_outb(ahd, port+1, (value >> 8) & 0xFF); -} - -static __inline uint32_t -ahd_inl(struct ahd_softc *ahd, u_int port) -{ - return ((ahd_inb(ahd, port)) - | (ahd_inb(ahd, port+1) << 8) - | (ahd_inb(ahd, port+2) << 16) - | (ahd_inb(ahd, port+3) << 24)); -} - -static __inline void -ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value) -{ - ahd_outb(ahd, port, (value) & 0xFF); - ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF); - ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF); - ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF); -} - -static __inline uint64_t -ahd_inq(struct ahd_softc *ahd, u_int port) -{ - return ((ahd_inb(ahd, port)) - | (ahd_inb(ahd, port+1) << 8) - | (ahd_inb(ahd, port+2) << 16) - | (ahd_inb(ahd, port+3) << 24) - | (((uint64_t)ahd_inb(ahd, port+4)) << 32) - | (((uint64_t)ahd_inb(ahd, port+5)) << 40) - | (((uint64_t)ahd_inb(ahd, port+6)) << 48) - | (((uint64_t)ahd_inb(ahd, port+7)) << 56)); -} - -static __inline void -ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value) -{ - ahd_outb(ahd, port, value & 0xFF); - ahd_outb(ahd, port+1, (value >> 8) & 0xFF); - ahd_outb(ahd, port+2, (value >> 16) & 0xFF); - ahd_outb(ahd, port+3, (value >> 24) & 0xFF); - ahd_outb(ahd, port+4, (value >> 32) & 0xFF); - ahd_outb(ahd, port+5, (value >> 40) & 0xFF); - ahd_outb(ahd, port+6, (value >> 48) & 0xFF); - ahd_outb(ahd, port+7, (value >> 56) & 0xFF); -} - -static __inline u_int +static inline u_int ahd_get_scbptr(struct ahd_softc *ahd) { AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), @@ -593,7 +313,7 @@ return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8)); } -static __inline void +static inline void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr) { AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), @@ -602,31 +322,31 @@ ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF); } -static __inline u_int +static inline u_int ahd_get_hnscb_qoff(struct ahd_softc *ahd) { return (ahd_inw_atomic(ahd, HNSCB_QOFF)); } -static __inline void +static inline void ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value) { ahd_outw_atomic(ahd, HNSCB_QOFF, value); } -static __inline u_int +static inline u_int ahd_get_hescb_qoff(struct ahd_softc *ahd) { return (ahd_inb(ahd, HESCB_QOFF)); } -static __inline void +static inline void ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value) { ahd_outb(ahd, HESCB_QOFF, value); } -static __inline u_int +static inline u_int ahd_get_snscb_qoff(struct ahd_softc *ahd) { u_int oldvalue; @@ -637,35 +357,35 @@ return (oldvalue); } -static __inline void +static inline void ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value) { AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); ahd_outw(ahd, SNSCB_QOFF, value); } -static __inline u_int +static inline u_int ahd_get_sescb_qoff(struct ahd_softc *ahd) { AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); return (ahd_inb(ahd, SESCB_QOFF)); } -static __inline void +static inline void ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value) { AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); ahd_outb(ahd, SESCB_QOFF, value); } -static __inline u_int +static inline u_int ahd_get_sdscb_qoff(struct ahd_softc *ahd) { AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8)); } -static __inline void +static inline void ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value) { AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); @@ -673,169 +393,24 @@ ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF); } -static __inline u_int -ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) -{ - u_int value; - - /* - * Workaround PCI-X Rev A. hardware bug. - * After a host read of SCB memory, the chip - * may become confused into thinking prefetch - * was required. This starts the discard timer - * running and can cause an unexpected discard - * timer interrupt. The work around is to read - * a normal register prior to the exhaustion of - * the discard timer. The mode pointer register - * has no side effects and so serves well for - * this purpose. - * - * Razor #528 - */ - value = ahd_inb(ahd, offset); - if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0) - ahd_inb(ahd, MODE_PTR); - return (value); -} - -static __inline u_int -ahd_inw_scbram(struct ahd_softc *ahd, u_int offset) -{ - return (ahd_inb_scbram(ahd, offset) - | (ahd_inb_scbram(ahd, offset+1) << 8)); -} - -static __inline uint32_t -ahd_inl_scbram(struct ahd_softc *ahd, u_int offset) -{ - return (ahd_inw_scbram(ahd, offset) - | (ahd_inw_scbram(ahd, offset+2) << 16)); -} - -static __inline uint64_t -ahd_inq_scbram(struct ahd_softc *ahd, u_int offset) -{ - return (ahd_inl_scbram(ahd, offset) - | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32); -} - -static __inline struct scb * -ahd_lookup_scb(struct ahd_softc *ahd, u_int tag) -{ - struct scb* scb; - - if (tag >= AHD_SCB_MAX) - return (NULL); - scb = ahd->scb_data.scbindex[tag]; - if (scb != NULL) - ahd_sync_scb(ahd, scb, - BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - return (scb); -} - -static __inline void -ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) -{ - struct hardware_scb *q_hscb; - struct map_node *q_hscb_map; - uint32_t saved_hscb_busaddr; - - /* - * Our queuing method is a bit tricky. The card - * knows in advance which HSCB (by address) to download, - * and we can't disappoint it. To achieve this, the next - * HSCB to download is saved off in ahd->next_queued_hscb. - * When we are called to queue "an arbitrary scb", - * we copy the contents of the incoming HSCB to the one - * the sequencer knows about, swap HSCB pointers and - * finally assign the SCB to the tag indexed location - * in the scb_array. This makes sure that we can still - * locate the correct SCB by SCB_TAG. - */ - q_hscb = ahd->next_queued_hscb; - q_hscb_map = ahd->next_queued_hscb_map; - saved_hscb_busaddr = q_hscb->hscb_busaddr; - memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); - q_hscb->hscb_busaddr = saved_hscb_busaddr; - q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; - - /* Now swap HSCB pointers. */ - ahd->next_queued_hscb = scb->hscb; - ahd->next_queued_hscb_map = scb->hscb_map; - scb->hscb = q_hscb; - scb->hscb_map = q_hscb_map; - - /* Now define the mapping from tag to SCB in the scbindex */ - ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; -} - -/* - * Tell the sequencer about a new transaction to execute. - */ -static __inline void -ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb) -{ - ahd_swap_with_next_hscb(ahd, scb); - - if (SCBID_IS_NULL(SCB_GET_TAG(scb))) - panic("Attempt to queue invalid SCB tag %x\n", - SCB_GET_TAG(scb)); - - /* - * Keep a history of SCBs we've downloaded in the qinfifo. - */ - ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb); - ahd->qinfifonext++; - - if (scb->sg_count != 0) - ahd_setup_data_scb(ahd, scb); - else - ahd_setup_noxfer_scb(ahd, scb); - ahd_setup_scb_common(ahd, scb); - - /* - * Make sure our data is consistent from the - * perspective of the adapter. - */ - ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - -#ifdef AHD_DEBUG - if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { - uint64_t host_dataptr; - - host_dataptr = ahd_le64toh(scb->hscb->dataptr); - printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n", - ahd_name(ahd), - SCB_GET_TAG(scb), scb->hscb->scsiid, - ahd_le32toh(scb->hscb->hscb_busaddr), - (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), - (u_int)(host_dataptr & 0xFFFFFFFF), - ahd_le32toh(scb->hscb->datacnt)); - } -#endif - /* Tell the adapter about the newly queued SCB */ - ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); -} - -static __inline uint8_t * +static inline uint8_t * ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb) { return (scb->sense_data); } -static __inline uint32_t +static inline uint32_t ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb) { return (scb->sense_busaddr); } /************************** Interrupt Processing ******************************/ -static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op); -static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op); -static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd); -static __inline int ahd_intr(struct ahd_softc *ahd); +static inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op); +static inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op); +int ahd_intr(struct ahd_softc *ahd); -static __inline void +static inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) { ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, @@ -843,7 +418,7 @@ /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op); } -static __inline void +static inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op) { #ifdef AHD_TARGET_MODE @@ -857,124 +432,4 @@ #endif } -/* - * See if the firmware has posted any completed commands - * into our in-core command complete fifos. - */ -#define AHD_RUN_QOUTFIFO 0x1 -#define AHD_RUN_TQINFIFO 0x2 -static __inline u_int -ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) -{ - u_int retval; - - retval = 0; - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, - /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo), - /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD); - if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag - == ahd->qoutfifonext_valid_tag) - retval |= AHD_RUN_QOUTFIFO; -#ifdef AHD_TARGET_MODE - if ((ahd->flags & AHD_TARGETROLE) != 0 - && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { - ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_map.dmamap, - ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), - /*len*/sizeof(struct target_cmd), - BUS_DMASYNC_POSTREAD); - if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0) - retval |= AHD_RUN_TQINFIFO; - } -#endif - return (retval); -} - -/* - * Catch an interrupt from the adapter - */ -static __inline int -ahd_intr(struct ahd_softc *ahd) -{ - u_int intstat; - - if ((ahd->pause & INTEN) == 0) { - /* - * Our interrupt is not enabled on the chip - * and may be disabled for re-entrancy reasons, - * so just return. This is likely just a shared - * interrupt. - */ - return (0); - } - - /* - * Instead of directly reading the interrupt status register, - * infer the cause of the interrupt by checking our in-core - * completion queues. This avoids a costly PCI bus read in - * most cases. - */ - if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0 - && (ahd_check_cmdcmpltqueues(ahd) != 0)) - intstat = CMDCMPLT; - else - intstat = ahd_inb(ahd, INTSTAT); - - if ((intstat & INT_PEND) == 0) - return (0); - - if (intstat & CMDCMPLT) { - ahd_outb(ahd, CLRINT, CLRCMDINT); - - /* - * Ensure that the chip sees that we've cleared - * this interrupt before we walk the output fifo. - * Otherwise, we may, due to posted bus writes, - * clear the interrupt after we finish the scan, - * and after the sequencer has added new entries - * and asserted the interrupt again. - */ - if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { - if (ahd_is_paused(ahd)) { - /* - * Potentially lost SEQINT. - * If SEQINTCODE is non-zero, - * simulate the SEQINT. - */ - if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT) - intstat |= SEQINT; - } - } else { - ahd_flush_device_writes(ahd); - } - ahd_run_qoutfifo(ahd); - ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++; - ahd->cmdcmplt_total++; -#ifdef AHD_TARGET_MODE - if ((ahd->flags & AHD_TARGETROLE) != 0) - ahd_run_tqinfifo(ahd, /*paused*/FALSE); -#endif - } - - /* - * Handle statuses that may invalidate our cached - * copy of INTSTAT separately. - */ - if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) { - /* Hot eject. Do nothing */ - } else if (intstat & HWERRINT) { - ahd_handle_hwerrint(ahd); - } else if ((intstat & (PCIINT|SPLTINT)) != 0) { - ahd->bus_intr(ahd); - } else { - - if ((intstat & SEQINT) != 0) - ahd_handle_seqint(ahd, intstat); - - if ((intstat & SCSIINT) != 0) - ahd_handle_scsiint(ahd, intstat); - } - return (1); -} - #endif /* _AIC79XX_INLINE_H_ */ diff -urN oldtree/drivers/scsi/aic7xxx/aic79xx_osm.c newtree/drivers/scsi/aic7xxx/aic79xx_osm.c --- oldtree/drivers/scsi/aic7xxx/aic79xx_osm.c 2006-09-29 14:03:21.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic79xx_osm.c 2006-09-29 16:15:37.000000000 -0400 @@ -293,7 +293,7 @@ * force all outstanding transactions to be serviced prior to a new * transaction. */ -uint32_t aic79xx_periodic_otag; +static uint32_t aic79xx_periodic_otag; /* Some storage boxes are using an LSI chip which has a bug making it * impossible to use aic79xx Rev B chip in 320 speeds. The following @@ -363,14 +363,16 @@ struct scsi_cmnd *); static void ahd_linux_setup_tag_info_global(char *p); static int aic79xx_setup(char *c); +static void ahd_freeze_simq(struct ahd_softc *ahd); +static void ahd_release_simq(struct ahd_softc *ahd); static int ahd_linux_unit; /****************************** Inlines ***************************************/ -static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); +static inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*); -static __inline void +static inline void ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb) { struct scsi_cmnd *cmd; @@ -418,7 +420,6 @@ strcat(bp, " "); ahd_controller_info(ahd, ahd_info); strcat(bp, ahd_info); - strcat(bp, "\n"); return (bp); } @@ -442,7 +443,7 @@ return rtn; } -static inline struct scsi_target ** +static struct scsi_target ** ahd_linux_target_in_softc(struct scsi_target *starget) { struct ahd_softc *ahd = @@ -2024,13 +2025,13 @@ cmd->scsi_done(cmd); } -void +static void ahd_freeze_simq(struct ahd_softc *ahd) { scsi_block_requests(ahd->platform_data->host); } -void +static void ahd_release_simq(struct ahd_softc *ahd) { scsi_unblock_requests(ahd->platform_data->host); diff -urN oldtree/drivers/scsi/aic7xxx/aic79xx_osm.h newtree/drivers/scsi/aic7xxx/aic79xx_osm.h --- oldtree/drivers/scsi/aic7xxx/aic79xx_osm.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic79xx_osm.h 2006-09-29 16:13:56.000000000 -0400 @@ -220,26 +220,6 @@ #endif #include "aic79xx.h" -/***************************** Timer Facilities *******************************/ -#define ahd_timer_init init_timer -#define ahd_timer_stop del_timer_sync -typedef void ahd_linux_callback_t (u_long); -static __inline void ahd_timer_reset(ahd_timer_t *timer, int usec, - ahd_callback_t *func, void *arg); - -static __inline void -ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) -{ - struct ahd_softc *ahd; - - ahd = (struct ahd_softc *)arg; - del_timer(timer); - timer->data = (u_long)arg; - timer->expires = jiffies + (usec * HZ)/1000000; - timer->function = (ahd_linux_callback_t*)func; - add_timer(timer); -} - /***************************** SMP support ************************************/ #include @@ -387,110 +367,17 @@ #define malloc(size, type, flags) kmalloc(size, flags) #define free(ptr, type) kfree(ptr) -static __inline void ahd_delay(long); -static __inline void -ahd_delay(long usec) +static inline void ahd_delay(int usec) { - /* - * udelay on Linux can have problems for - * multi-millisecond waits. Wait at most - * 1024us per call. - */ - while (usec > 0) { - udelay(usec % 1024); - usec -= 1024; - } + udelay(usec); } - /***************************** Low Level I/O **********************************/ -static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port); -static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port); -static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val); -static __inline void ahd_outw_atomic(struct ahd_softc * ahd, +uint8_t ahd_inb(struct ahd_softc * ahd, long port); +uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port); +void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val); +void ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val); -static __inline void ahd_outsb(struct ahd_softc * ahd, long port, - uint8_t *, int count); -static __inline void ahd_insb(struct ahd_softc * ahd, long port, - uint8_t *, int count); - -static __inline uint8_t -ahd_inb(struct ahd_softc * ahd, long port) -{ - uint8_t x; - - if (ahd->tags[0] == BUS_SPACE_MEMIO) { - x = readb(ahd->bshs[0].maddr + port); - } else { - x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); - } - mb(); - return (x); -} - -static __inline uint16_t -ahd_inw_atomic(struct ahd_softc * ahd, long port) -{ - uint8_t x; - - if (ahd->tags[0] == BUS_SPACE_MEMIO) { - x = readw(ahd->bshs[0].maddr + port); - } else { - x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF)); - } - mb(); - return (x); -} - -static __inline void -ahd_outb(struct ahd_softc * ahd, long port, uint8_t val) -{ - if (ahd->tags[0] == BUS_SPACE_MEMIO) { - writeb(val, ahd->bshs[0].maddr + port); - } else { - outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); - } - mb(); -} - -static __inline void -ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val) -{ - if (ahd->tags[0] == BUS_SPACE_MEMIO) { - writew(val, ahd->bshs[0].maddr + port); - } else { - outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF)); - } - mb(); -} - -static __inline void -ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count) -{ - int i; - - /* - * There is probably a more efficient way to do this on Linux - * but we don't use this for anything speed critical and this - * should work. - */ - for (i = 0; i < count; i++) - ahd_outb(ahd, port, *array++); -} - -static __inline void -ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count) -{ - int i; - - /* - * There is probably a more efficient way to do this on Linux - * but we don't use this for anything speed critical and this - * should work. - */ - for (i = 0; i < count; i++) - *array++ = ahd_inb(ahd, port); -} /**************************** Initialization **********************************/ int ahd_linux_register_host(struct ahd_softc *, @@ -506,23 +393,20 @@ int pos; }; -void ahd_format_transinfo(struct info_str *info, - struct ahd_transinfo *tinfo); - /******************************** Locking *************************************/ -static __inline void +static inline void ahd_lockinit(struct ahd_softc *ahd) { spin_lock_init(&ahd->platform_data->spin_lock); } -static __inline void +static inline void ahd_lock(struct ahd_softc *ahd, unsigned long *flags) { spin_lock_irqsave(&ahd->platform_data->spin_lock, *flags); } -static __inline void +static inline void ahd_unlock(struct ahd_softc *ahd, unsigned long *flags) { spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags); @@ -582,8 +466,6 @@ #define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ #define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ -extern struct pci_driver aic79xx_pci_driver; - typedef enum { AHD_POWER_STATE_D0, @@ -601,10 +483,11 @@ int ahd_pci_map_registers(struct ahd_softc *ahd); int ahd_pci_map_int(struct ahd_softc *ahd); -static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci, +void ahd_BUG_bad_pci_rw_size(void); +static inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width); -static __inline uint32_t +static inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width) { switch (width) { @@ -628,17 +511,17 @@ return (retval); } default: - panic("ahd_pci_read_config: Read size too big"); + ahd_BUG_bad_pci_rw_size(); /* NOTREACHED */ return (0); } } -static __inline void ahd_pci_write_config(ahd_dev_softc_t pci, +static inline void ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width); -static __inline void +static inline void ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width) { switch (width) { @@ -652,34 +535,34 @@ pci_write_config_dword(pci, reg, value); break; default: - panic("ahd_pci_write_config: Write size too big"); + ahd_BUG_bad_pci_rw_size(); /* NOTREACHED */ } } -static __inline int ahd_get_pci_function(ahd_dev_softc_t); -static __inline int +static inline int ahd_get_pci_function(ahd_dev_softc_t); +static inline int ahd_get_pci_function(ahd_dev_softc_t pci) { return (PCI_FUNC(pci->devfn)); } -static __inline int ahd_get_pci_slot(ahd_dev_softc_t); -static __inline int +static inline int ahd_get_pci_slot(ahd_dev_softc_t); +static inline int ahd_get_pci_slot(ahd_dev_softc_t pci) { return (PCI_SLOT(pci->devfn)); } -static __inline int ahd_get_pci_bus(ahd_dev_softc_t); -static __inline int +static inline int ahd_get_pci_bus(ahd_dev_softc_t); +static inline int ahd_get_pci_bus(ahd_dev_softc_t pci) { return (pci->bus->number); } -static __inline void ahd_flush_device_writes(struct ahd_softc *); -static __inline void +static inline void ahd_flush_device_writes(struct ahd_softc *); +static inline void ahd_flush_device_writes(struct ahd_softc *ahd) { /* XXX Is this sufficient for all architectures??? */ @@ -691,81 +574,81 @@ off_t, int, int); /*********************** Transaction Access Wrappers **************************/ -static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t); -static __inline void ahd_set_transaction_status(struct scb *, uint32_t); -static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t); -static __inline void ahd_set_scsi_status(struct scb *, uint32_t); -static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd); -static __inline uint32_t ahd_get_transaction_status(struct scb *); -static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd); -static __inline uint32_t ahd_get_scsi_status(struct scb *); -static __inline void ahd_set_transaction_tag(struct scb *, int, u_int); -static __inline u_long ahd_get_transfer_length(struct scb *); -static __inline int ahd_get_transfer_dir(struct scb *); -static __inline void ahd_set_residual(struct scb *, u_long); -static __inline void ahd_set_sense_residual(struct scb *scb, u_long resid); -static __inline u_long ahd_get_residual(struct scb *); -static __inline u_long ahd_get_sense_residual(struct scb *); -static __inline int ahd_perform_autosense(struct scb *); -static __inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *, +static inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t); +static inline void ahd_set_transaction_status(struct scb *, uint32_t); +static inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t); +static inline void ahd_set_scsi_status(struct scb *, uint32_t); +static inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd); +static inline uint32_t ahd_get_transaction_status(struct scb *); +static inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd); +static inline uint32_t ahd_get_scsi_status(struct scb *); +static inline void ahd_set_transaction_tag(struct scb *, int, u_int); +static inline u_long ahd_get_transfer_length(struct scb *); +static inline int ahd_get_transfer_dir(struct scb *); +static inline void ahd_set_residual(struct scb *, u_long); +static inline void ahd_set_sense_residual(struct scb *scb, u_long resid); +static inline u_long ahd_get_residual(struct scb *); +static inline u_long ahd_get_sense_residual(struct scb *); +static inline int ahd_perform_autosense(struct scb *); +static inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *, struct scb *); -static __inline void ahd_notify_xfer_settings_change(struct ahd_softc *, +static inline void ahd_notify_xfer_settings_change(struct ahd_softc *, struct ahd_devinfo *); -static __inline void ahd_platform_scb_free(struct ahd_softc *ahd, +static inline void ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb); -static __inline void ahd_freeze_scb(struct scb *scb); +static inline void ahd_freeze_scb(struct scb *scb); -static __inline +static inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status) { cmd->result &= ~(CAM_STATUS_MASK << 16); cmd->result |= status << 16; } -static __inline +static inline void ahd_set_transaction_status(struct scb *scb, uint32_t status) { ahd_cmd_set_transaction_status(scb->io_ctx,status); } -static __inline +static inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status) { cmd->result &= ~0xFFFF; cmd->result |= status; } -static __inline +static inline void ahd_set_scsi_status(struct scb *scb, uint32_t status) { ahd_cmd_set_scsi_status(scb->io_ctx, status); } -static __inline +static inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd) { return ((cmd->result >> 16) & CAM_STATUS_MASK); } -static __inline +static inline uint32_t ahd_get_transaction_status(struct scb *scb) { return (ahd_cmd_get_transaction_status(scb->io_ctx)); } -static __inline +static inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd) { return (cmd->result & 0xFFFF); } -static __inline +static inline uint32_t ahd_get_scsi_status(struct scb *scb) { return (ahd_cmd_get_scsi_status(scb->io_ctx)); } -static __inline +static inline void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type) { /* @@ -774,43 +657,43 @@ */ } -static __inline +static inline u_long ahd_get_transfer_length(struct scb *scb) { return (scb->platform_data->xfer_len); } -static __inline +static inline int ahd_get_transfer_dir(struct scb *scb) { return (scb->io_ctx->sc_data_direction); } -static __inline +static inline void ahd_set_residual(struct scb *scb, u_long resid) { scb->io_ctx->resid = resid; } -static __inline +static inline void ahd_set_sense_residual(struct scb *scb, u_long resid) { scb->platform_data->sense_resid = resid; } -static __inline +static inline u_long ahd_get_residual(struct scb *scb) { return (scb->io_ctx->resid); } -static __inline +static inline u_long ahd_get_sense_residual(struct scb *scb) { return (scb->platform_data->sense_resid); } -static __inline +static inline int ahd_perform_autosense(struct scb *scb) { /* @@ -821,20 +704,20 @@ return (1); } -static __inline uint32_t +static inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb) { return (sizeof(struct scsi_sense_data)); } -static __inline void +static inline void ahd_notify_xfer_settings_change(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) { /* Nothing to do here for linux */ } -static __inline void +static inline void ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb) { ahd->flags &= ~AHD_RESOURCE_SHORTAGE; @@ -844,10 +727,8 @@ void ahd_platform_free(struct ahd_softc *ahd); void ahd_platform_init(struct ahd_softc *ahd); void ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb); -void ahd_freeze_simq(struct ahd_softc *ahd); -void ahd_release_simq(struct ahd_softc *ahd); -static __inline void +static inline void ahd_freeze_scb(struct scb *scb) { if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) { diff -urN oldtree/drivers/scsi/aic7xxx/aic79xx_osm_pci.c newtree/drivers/scsi/aic7xxx/aic79xx_osm_pci.c --- oldtree/drivers/scsi/aic7xxx/aic79xx_osm_pci.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic79xx_osm_pci.c 2006-09-29 16:12:42.000000000 -0400 @@ -82,7 +82,7 @@ MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); -struct pci_driver aic79xx_pci_driver = { +static struct pci_driver aic79xx_pci_driver = { .name = "aic79xx", .probe = ahd_linux_pci_dev_probe, .remove = ahd_linux_pci_dev_remove, diff -urN oldtree/drivers/scsi/aic7xxx/aic79xx_pci.c newtree/drivers/scsi/aic7xxx/aic79xx_pci.c --- oldtree/drivers/scsi/aic7xxx/aic79xx_pci.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic79xx_pci.c 2006-09-29 16:13:40.000000000 -0400 @@ -51,7 +51,7 @@ #include "aic79xx_pci.h" -static __inline uint64_t +static inline uint64_t ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) { uint64_t id; @@ -97,7 +97,7 @@ static ahd_device_setup_t ahd_aic7902_setup; static ahd_device_setup_t ahd_aic790X_setup; -struct ahd_pci_identity ahd_pci_ident_table [] = +static struct ahd_pci_identity ahd_pci_ident_table [] = { /* aic7901 based controllers */ { @@ -201,7 +201,7 @@ } }; -const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table); +static const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table); #define DEVCONFIG 0x40 #define PCIXINITPAT 0x0000E000ul @@ -245,6 +245,7 @@ static void ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control); static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat); +static void ahd_pci_intr(struct ahd_softc *ahd); struct ahd_pci_identity * ahd_find_pci_device(ahd_dev_softc_t pci) @@ -757,7 +758,7 @@ "%s: Address or Write Phase Parity Error Detected in %s.\n" }; -void +static void ahd_pci_intr(struct ahd_softc *ahd) { uint8_t pci_status[8]; diff -urN oldtree/drivers/scsi/aic7xxx/aic79xx_proc.c newtree/drivers/scsi/aic7xxx/aic79xx_proc.c --- oldtree/drivers/scsi/aic7xxx/aic79xx_proc.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic79xx_proc.c 2006-09-29 16:12:42.000000000 -0400 @@ -136,7 +136,7 @@ return (len); } -void +static void ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) { u_int speed; diff -urN oldtree/drivers/scsi/aic7xxx/aic7xxx.h newtree/drivers/scsi/aic7xxx/aic7xxx.h --- oldtree/drivers/scsi/aic7xxx/aic7xxx.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic7xxx.h 2006-09-29 16:13:56.000000000 -0400 @@ -1135,8 +1135,6 @@ char *name; ahc_device_setup_t *setup; }; -extern struct ahc_pci_identity ahc_pci_ident_table[]; -extern const u_int ahc_num_pci_devs; /***************************** VL/EISA Declarations ***************************/ struct aic7770_identity { @@ -1193,21 +1191,15 @@ int ahc_resume(struct ahc_softc *ahc); void ahc_set_unit(struct ahc_softc *, int); void ahc_set_name(struct ahc_softc *, char *); -void ahc_alloc_scbs(struct ahc_softc *ahc); void ahc_free(struct ahc_softc *ahc); int ahc_reset(struct ahc_softc *ahc, int reinit); void ahc_shutdown(void *arg); /*************************** Interrupt Services *******************************/ void ahc_clear_intstat(struct ahc_softc *ahc); -void ahc_run_qoutfifo(struct ahc_softc *ahc); #ifdef AHC_TARGET_MODE void ahc_run_tqinfifo(struct ahc_softc *ahc, int paused); #endif -void ahc_handle_brkadrint(struct ahc_softc *ahc); -void ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat); -void ahc_handle_scsiint(struct ahc_softc *ahc, - u_int intstat); void ahc_clear_critical_section(struct ahc_softc *ahc); /***************************** Error Recovery *********************************/ diff -urN oldtree/drivers/scsi/aic7xxx/aic7xxx_core.c newtree/drivers/scsi/aic7xxx/aic7xxx_core.c --- oldtree/drivers/scsi/aic7xxx/aic7xxx_core.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic7xxx_core.c 2006-09-29 16:13:56.000000000 -0400 @@ -50,6 +50,377 @@ #include #endif +static void ahc_alloc_scbs(struct ahc_softc *ahc); +static void ahc_handle_brkadrint(struct ahc_softc *ahc); +static void ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat); +static void ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat); +static void ahc_run_qoutfifo(struct ahc_softc *ahc); + +/***************************** Low Level I/O **********************************/ +uint8_t +ahc_inb(struct ahc_softc * ahc, long port) +{ + uint8_t x; + + if (ahc->tag == BUS_SPACE_MEMIO) { + x = readb(ahc->bsh.maddr + port); + } else { + x = inb(ahc->bsh.ioport + port); + } + mb(); + return (x); +} + +void +ahc_outb(struct ahc_softc * ahc, long port, uint8_t val) +{ + if (ahc->tag == BUS_SPACE_MEMIO) { + writeb(val, ahc->bsh.maddr + port); + } else { + outb(val, ahc->bsh.ioport + port); + } + mb(); +} + +static void +ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count) +{ + int i; + + /* + * There is probably a more efficient way to do this on Linux + * but we don't use this for anything speed critical and this + * should work. + */ + for (i = 0; i < count; i++) + ahc_outb(ahc, port, *array++); +} + +#ifdef AHC_DUMP_SEQ +static void +ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count) +{ + int i; + + /* + * There is probably a more efficient way to do this on Linux + * but we don't use this for anything speed critical and this + * should work. + */ + for (i = 0; i < count; i++) + *array++ = ahc_inb(ahc, port); +} +#endif /* AHC_DUMP_SEQ */ + +/*********************** Miscelaneous Support Functions ***********************/ +uint16_t +ahc_inw(struct ahc_softc *ahc, u_int port) +{ + return ((ahc_inb(ahc, port+1) << 8) | ahc_inb(ahc, port)); +} + +void +ahc_outw(struct ahc_softc *ahc, u_int port, u_int value) +{ + ahc_outb(ahc, port, value & 0xFF); + ahc_outb(ahc, port+1, (value >> 8) & 0xFF); +} + +uint32_t +ahc_inl(struct ahc_softc *ahc, u_int port) +{ + return ((ahc_inb(ahc, port)) + | (ahc_inb(ahc, port+1) << 8) + | (ahc_inb(ahc, port+2) << 16) + | (ahc_inb(ahc, port+3) << 24)); +} + +void +ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value) +{ + ahc_outb(ahc, port, (value) & 0xFF); + ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF); + ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF); + ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF); +} + +#if 0 + +uint64_t +ahc_inq(struct ahc_softc *ahc, u_int port) +{ + return ((ahc_inb(ahc, port)) + | (ahc_inb(ahc, port+1) << 8) + | (ahc_inb(ahc, port+2) << 16) + | (ahc_inb(ahc, port+3) << 24) + | (((uint64_t)ahc_inb(ahc, port+4)) << 32) + | (((uint64_t)ahc_inb(ahc, port+5)) << 40) + | (((uint64_t)ahc_inb(ahc, port+6)) << 48) + | (((uint64_t)ahc_inb(ahc, port+7)) << 56)); +} + +void +ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value) +{ + ahc_outb(ahc, port, value & 0xFF); + ahc_outb(ahc, port+1, (value >> 8) & 0xFF); + ahc_outb(ahc, port+2, (value >> 16) & 0xFF); + ahc_outb(ahc, port+3, (value >> 24) & 0xFF); + ahc_outb(ahc, port+4, (value >> 32) & 0xFF); + ahc_outb(ahc, port+5, (value >> 40) & 0xFF); + ahc_outb(ahc, port+6, (value >> 48) & 0xFF); + ahc_outb(ahc, port+7, (value >> 56) & 0xFF); +} + +#endif /* 0 */ + +/* + * Get a free scb. If there are none, see if we can allocate a new SCB. + */ +struct scb * +ahc_get_scb(struct ahc_softc *ahc) +{ + struct scb *scb; + + if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) { + ahc_alloc_scbs(ahc); + scb = SLIST_FIRST(&ahc->scb_data->free_scbs); + if (scb == NULL) + return (NULL); + } + SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle); + return (scb); +} + +/* + * Return an SCB resource to the free list. + */ +void +ahc_free_scb(struct ahc_softc *ahc, struct scb *scb) +{ + struct hardware_scb *hscb; + + hscb = scb->hscb; + /* Clean up for the next user */ + ahc->scb_data->scbindex[hscb->tag] = NULL; + scb->flags = SCB_FREE; + hscb->control = 0; + + SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle); + + /* Notify the OSM that a resource is now available. */ + ahc_platform_scb_free(ahc, scb); +} + +struct scb * +ahc_lookup_scb(struct ahc_softc *ahc, u_int tag) +{ + struct scb* scb; + + scb = ahc->scb_data->scbindex[tag]; + if (scb != NULL) + ahc_sync_scb(ahc, scb, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + return (scb); +} + +static void +ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb) +{ + struct hardware_scb *q_hscb; + u_int saved_tag; + + /* + * Our queuing method is a bit tricky. The card + * knows in advance which HSCB to download, and we + * can't disappoint it. To achieve this, the next + * SCB to download is saved off in ahc->next_queued_scb. + * When we are called to queue "an arbitrary scb", + * we copy the contents of the incoming HSCB to the one + * the sequencer knows about, swap HSCB pointers and + * finally assign the SCB to the tag indexed location + * in the scb_array. This makes sure that we can still + * locate the correct SCB by SCB_TAG. + */ + q_hscb = ahc->next_queued_scb->hscb; + saved_tag = q_hscb->tag; + memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); + if ((scb->flags & SCB_CDB32_PTR) != 0) { + q_hscb->shared_data.cdb_ptr = + ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) + + offsetof(struct hardware_scb, cdb32)); + } + q_hscb->tag = saved_tag; + q_hscb->next = scb->hscb->tag; + + /* Now swap HSCB pointers. */ + ahc->next_queued_scb->hscb = scb->hscb; + scb->hscb = q_hscb; + + /* Now define the mapping from tag to SCB in the scbindex */ + ahc->scb_data->scbindex[scb->hscb->tag] = scb; +} + +/* + * Tell the sequencer about a new transaction to execute. + */ +void +ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb) +{ + ahc_swap_with_next_hscb(ahc, scb); + + if (scb->hscb->tag == SCB_LIST_NULL + || scb->hscb->next == SCB_LIST_NULL) + panic("Attempt to queue invalid SCB tag %x:%x\n", + scb->hscb->tag, scb->hscb->next); + + /* + * Setup data "oddness". + */ + scb->hscb->lun &= LID; + if (ahc_get_transfer_length(scb) & 0x1) + scb->hscb->lun |= SCB_XFERLEN_ODD; + + /* + * Keep a history of SCBs we've downloaded in the qinfifo. + */ + ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag; + + /* + * Make sure our data is consistent from the + * perspective of the adapter. + */ + ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + + /* Tell the adapter about the newly queued SCB */ + if ((ahc->features & AHC_QUEUE_REGS) != 0) { + ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); + } else { + if ((ahc->features & AHC_AUTOPAUSE) == 0) + ahc_pause(ahc); + ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); + if ((ahc->features & AHC_AUTOPAUSE) == 0) + ahc_unpause(ahc); + } +} + +/************************** Interrupt Processing ******************************/ +/* + * See if the firmware has posted any completed commands + * into our in-core command complete fifos. + */ +#define AHC_RUN_QOUTFIFO 0x1 +#define AHC_RUN_TQINFIFO 0x2 +static u_int +ahc_check_cmdcmpltqueues(struct ahc_softc *ahc) +{ + u_int retval; + + retval = 0; + ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, + /*offset*/ahc->qoutfifonext, /*len*/1, + BUS_DMASYNC_POSTREAD); + if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) + retval |= AHC_RUN_QOUTFIFO; +#ifdef AHC_TARGET_MODE + if ((ahc->flags & AHC_TARGETROLE) != 0 + && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) { + ahc_dmamap_sync(ahc, ahc->shared_data_dmat, + ahc->shared_data_dmamap, + ahc_targetcmd_offset(ahc, ahc->tqinfifofnext), + /*len*/sizeof(struct target_cmd), + BUS_DMASYNC_POSTREAD); + if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0) + retval |= AHC_RUN_TQINFIFO; + } +#endif + return (retval); +} + +/* + * Catch an interrupt from the adapter + */ +int +ahc_intr(struct ahc_softc *ahc) +{ + u_int intstat; + + if ((ahc->pause & INTEN) == 0) { + /* + * Our interrupt is not enabled on the chip + * and may be disabled for re-entrancy reasons, + * so just return. This is likely just a shared + * interrupt. + */ + return (0); + } + /* + * Instead of directly reading the interrupt status register, + * infer the cause of the interrupt by checking our in-core + * completion queues. This avoids a costly PCI bus read in + * most cases. + */ + if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0 + && (ahc_check_cmdcmpltqueues(ahc) != 0)) + intstat = CMDCMPLT; + else { + intstat = ahc_inb(ahc, INTSTAT); + } + + if ((intstat & INT_PEND) == 0) { +#if AHC_PCI_CONFIG > 0 + if (ahc->unsolicited_ints > 500) { + ahc->unsolicited_ints = 0; + if ((ahc->chip & AHC_PCI) != 0 + && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0) + ahc->bus_intr(ahc); + } +#endif + ahc->unsolicited_ints++; + return (0); + } + ahc->unsolicited_ints = 0; + + if (intstat & CMDCMPLT) { + ahc_outb(ahc, CLRINT, CLRCMDINT); + + /* + * Ensure that the chip sees that we've cleared + * this interrupt before we walk the output fifo. + * Otherwise, we may, due to posted bus writes, + * clear the interrupt after we finish the scan, + * and after the sequencer has added new entries + * and asserted the interrupt again. + */ + ahc_flush_device_writes(ahc); + ahc_run_qoutfifo(ahc); +#ifdef AHC_TARGET_MODE + if ((ahc->flags & AHC_TARGETROLE) != 0) + ahc_run_tqinfifo(ahc, /*paused*/FALSE); +#endif + } + + /* + * Handle statuses that may invalidate our cached + * copy of INTSTAT separately. + */ + if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) { + /* Hot eject. Do nothing */ + } else if (intstat & BRKADRINT) { + ahc_handle_brkadrint(ahc); + } else if ((intstat & (SEQINT|SCSIINT)) != 0) { + + ahc_pause_bug_fix(ahc); + + if ((intstat & SEQINT) != 0) + ahc_handle_seqint(ahc, intstat); + + if ((intstat & SCSIINT) != 0) + ahc_handle_scsiint(ahc, intstat); + } + return (1); +} + /***************************** Lookup Tables **********************************/ char *ahc_chip_names[] = { @@ -302,7 +673,7 @@ } /************************* Input/Output Queues ********************************/ -void +static void ahc_run_qoutfifo(struct ahc_softc *ahc) { struct scb *scb; @@ -374,7 +745,7 @@ } /************************* Interrupt Handling *********************************/ -void +static void ahc_handle_brkadrint(struct ahc_softc *ahc) { /* @@ -403,7 +774,7 @@ ahc_shutdown(ahc); } -void +static void ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat) { struct scb *scb; @@ -953,7 +1324,7 @@ ahc_unpause(ahc); } -void +static void ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat) { u_int scb_index; @@ -4365,7 +4736,7 @@ free(scb_data->scbarray, M_DEVBUF); } -void +static void ahc_alloc_scbs(struct ahc_softc *ahc) { struct scb_data *scb_data; diff -urN oldtree/drivers/scsi/aic7xxx/aic7xxx_inline.h newtree/drivers/scsi/aic7xxx/aic7xxx_inline.h --- oldtree/drivers/scsi/aic7xxx/aic7xxx_inline.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic7xxx_inline.h 2006-09-29 16:13:56.000000000 -0400 @@ -46,10 +46,10 @@ #define _AIC7XXX_INLINE_H_ /************************* Sequencer Execution Control ************************/ -static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc); -static __inline int ahc_is_paused(struct ahc_softc *ahc); -static __inline void ahc_pause(struct ahc_softc *ahc); -static __inline void ahc_unpause(struct ahc_softc *ahc); +static inline void ahc_pause_bug_fix(struct ahc_softc *ahc); +static inline int ahc_is_paused(struct ahc_softc *ahc); +static inline void ahc_pause(struct ahc_softc *ahc); +static inline void ahc_unpause(struct ahc_softc *ahc); /* * Work around any chip bugs related to halting sequencer execution. @@ -59,7 +59,7 @@ * manual pause while accessing scb ram, accesses to certain registers * will hang the system (infinite pci retries). */ -static __inline void +static inline void ahc_pause_bug_fix(struct ahc_softc *ahc) { if ((ahc->features & AHC_ULTRA2) != 0) @@ -70,7 +70,7 @@ * Determine whether the sequencer has halted code execution. * Returns non-zero status if the sequencer is stopped. */ -static __inline int +static inline int ahc_is_paused(struct ahc_softc *ahc) { return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0); @@ -83,7 +83,7 @@ * cleared in the SEQCTL register. The sequencer may use PAUSEDIS * for critical sections. */ -static __inline void +static inline void ahc_pause(struct ahc_softc *ahc) { ahc_outb(ahc, HCNTRL, ahc->pause); @@ -108,7 +108,7 @@ * into our interrupt handler and dealing with this new * condition. */ -static __inline void +static inline void ahc_unpause(struct ahc_softc *ahc) { if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0) @@ -116,14 +116,14 @@ } /*********************** Untagged Transaction Routines ************************/ -static __inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc); -static __inline void ahc_release_untagged_queues(struct ahc_softc *ahc); +static inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc); +static inline void ahc_release_untagged_queues(struct ahc_softc *ahc); /* * Block our completion routine from starting the next untagged * transaction for this target or target lun. */ -static __inline void +static inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc) { if ((ahc->flags & AHC_SCB_BTT) == 0) @@ -136,7 +136,7 @@ * to be acquired recursively. Once the count drops to zero, the * transaction queues will be run. */ -static __inline void +static inline void ahc_release_untagged_queues(struct ahc_softc *ahc) { if ((ahc->flags & AHC_SCB_BTT) == 0) { @@ -147,23 +147,23 @@ } /************************** Memory mapping routines ***************************/ -static __inline struct ahc_dma_seg * +static inline struct ahc_dma_seg * ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr); -static __inline uint32_t +static inline uint32_t ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg); -static __inline uint32_t +static inline uint32_t ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index); -static __inline void ahc_sync_scb(struct ahc_softc *ahc, +static inline void ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op); -static __inline void ahc_sync_sglist(struct ahc_softc *ahc, +static inline void ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op); -static __inline uint32_t +static inline uint32_t ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index); -static __inline struct ahc_dma_seg * +static inline struct ahc_dma_seg * ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr) { int sg_index; @@ -175,7 +175,7 @@ return (&scb->sg_list[sg_index]); } -static __inline uint32_t +static inline uint32_t ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg) { int sg_index; @@ -186,14 +186,14 @@ return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list))); } -static __inline uint32_t +static inline uint32_t ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index) { return (ahc->scb_data->hscb_busaddr + (sizeof(struct hardware_scb) * index)); } -static __inline void +static inline void ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op) { ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat, @@ -202,7 +202,7 @@ /*len*/sizeof(*scb->hscb), op); } -static __inline void +static inline void ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op) { if (scb->sg_count == 0) @@ -214,16 +214,16 @@ /*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op); } -static __inline uint32_t +static inline uint32_t ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index) { return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo); } /******************************** Debugging ***********************************/ -static __inline char *ahc_name(struct ahc_softc *ahc); +static inline char *ahc_name(struct ahc_softc *ahc); -static __inline char * +static inline char * ahc_name(struct ahc_softc *ahc) { return (ahc->name); @@ -231,35 +231,27 @@ /*********************** Miscelaneous Support Functions ***********************/ -static __inline void ahc_update_residual(struct ahc_softc *ahc, +static inline void ahc_update_residual(struct ahc_softc *ahc, struct scb *scb); -static __inline struct ahc_initiator_tinfo * +static inline struct ahc_initiator_tinfo * ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id, u_int remote_id, struct ahc_tmode_tstate **tstate); -static __inline uint16_t - ahc_inw(struct ahc_softc *ahc, u_int port); -static __inline void ahc_outw(struct ahc_softc *ahc, u_int port, - u_int value); -static __inline uint32_t - ahc_inl(struct ahc_softc *ahc, u_int port); -static __inline void ahc_outl(struct ahc_softc *ahc, u_int port, - uint32_t value); -static __inline uint64_t - ahc_inq(struct ahc_softc *ahc, u_int port); -static __inline void ahc_outq(struct ahc_softc *ahc, u_int port, - uint64_t value); -static __inline struct scb* - ahc_get_scb(struct ahc_softc *ahc); -static __inline void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb); -static __inline void ahc_swap_with_next_hscb(struct ahc_softc *ahc, - struct scb *scb); -static __inline void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb); -static __inline struct scsi_sense_data * +uint16_t ahc_inw(struct ahc_softc *ahc, u_int port); +void ahc_outw(struct ahc_softc *ahc, u_int port, u_int value); +uint32_t ahc_inl(struct ahc_softc *ahc, u_int port); +void ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value); +struct scb* + ahc_get_scb(struct ahc_softc *ahc); +void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb); +struct scb * + ahc_lookup_scb(struct ahc_softc *ahc, u_int tag); +void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb); +static inline struct scsi_sense_data * ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb); -static __inline uint32_t +static inline uint32_t ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb); @@ -267,7 +259,7 @@ * Determine whether the sequencer reported a residual * for this SCB/transaction. */ -static __inline void +static inline void ahc_update_residual(struct ahc_softc *ahc, struct scb *scb) { uint32_t sgptr; @@ -281,7 +273,7 @@ * Return pointers to the transfer negotiation information * for the specified our_id/remote_id pair. */ -static __inline struct ahc_initiator_tinfo * +static inline struct ahc_initiator_tinfo * ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id, u_int remote_id, struct ahc_tmode_tstate **tstate) { @@ -297,194 +289,7 @@ return (&(*tstate)->transinfo[remote_id]); } -static __inline uint16_t -ahc_inw(struct ahc_softc *ahc, u_int port) -{ - return ((ahc_inb(ahc, port+1) << 8) | ahc_inb(ahc, port)); -} - -static __inline void -ahc_outw(struct ahc_softc *ahc, u_int port, u_int value) -{ - ahc_outb(ahc, port, value & 0xFF); - ahc_outb(ahc, port+1, (value >> 8) & 0xFF); -} - -static __inline uint32_t -ahc_inl(struct ahc_softc *ahc, u_int port) -{ - return ((ahc_inb(ahc, port)) - | (ahc_inb(ahc, port+1) << 8) - | (ahc_inb(ahc, port+2) << 16) - | (ahc_inb(ahc, port+3) << 24)); -} - -static __inline void -ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value) -{ - ahc_outb(ahc, port, (value) & 0xFF); - ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF); - ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF); - ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF); -} - -static __inline uint64_t -ahc_inq(struct ahc_softc *ahc, u_int port) -{ - return ((ahc_inb(ahc, port)) - | (ahc_inb(ahc, port+1) << 8) - | (ahc_inb(ahc, port+2) << 16) - | (ahc_inb(ahc, port+3) << 24) - | (((uint64_t)ahc_inb(ahc, port+4)) << 32) - | (((uint64_t)ahc_inb(ahc, port+5)) << 40) - | (((uint64_t)ahc_inb(ahc, port+6)) << 48) - | (((uint64_t)ahc_inb(ahc, port+7)) << 56)); -} - -static __inline void -ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value) -{ - ahc_outb(ahc, port, value & 0xFF); - ahc_outb(ahc, port+1, (value >> 8) & 0xFF); - ahc_outb(ahc, port+2, (value >> 16) & 0xFF); - ahc_outb(ahc, port+3, (value >> 24) & 0xFF); - ahc_outb(ahc, port+4, (value >> 32) & 0xFF); - ahc_outb(ahc, port+5, (value >> 40) & 0xFF); - ahc_outb(ahc, port+6, (value >> 48) & 0xFF); - ahc_outb(ahc, port+7, (value >> 56) & 0xFF); -} - -/* - * Get a free scb. If there are none, see if we can allocate a new SCB. - */ -static __inline struct scb * -ahc_get_scb(struct ahc_softc *ahc) -{ - struct scb *scb; - - if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) { - ahc_alloc_scbs(ahc); - scb = SLIST_FIRST(&ahc->scb_data->free_scbs); - if (scb == NULL) - return (NULL); - } - SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle); - return (scb); -} - -/* - * Return an SCB resource to the free list. - */ -static __inline void -ahc_free_scb(struct ahc_softc *ahc, struct scb *scb) -{ - struct hardware_scb *hscb; - - hscb = scb->hscb; - /* Clean up for the next user */ - ahc->scb_data->scbindex[hscb->tag] = NULL; - scb->flags = SCB_FREE; - hscb->control = 0; - - SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle); - - /* Notify the OSM that a resource is now available. */ - ahc_platform_scb_free(ahc, scb); -} - -static __inline struct scb * -ahc_lookup_scb(struct ahc_softc *ahc, u_int tag) -{ - struct scb* scb; - - scb = ahc->scb_data->scbindex[tag]; - if (scb != NULL) - ahc_sync_scb(ahc, scb, - BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - return (scb); -} - -static __inline void -ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb) -{ - struct hardware_scb *q_hscb; - u_int saved_tag; - - /* - * Our queuing method is a bit tricky. The card - * knows in advance which HSCB to download, and we - * can't disappoint it. To achieve this, the next - * SCB to download is saved off in ahc->next_queued_scb. - * When we are called to queue "an arbitrary scb", - * we copy the contents of the incoming HSCB to the one - * the sequencer knows about, swap HSCB pointers and - * finally assign the SCB to the tag indexed location - * in the scb_array. This makes sure that we can still - * locate the correct SCB by SCB_TAG. - */ - q_hscb = ahc->next_queued_scb->hscb; - saved_tag = q_hscb->tag; - memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); - if ((scb->flags & SCB_CDB32_PTR) != 0) { - q_hscb->shared_data.cdb_ptr = - ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag) - + offsetof(struct hardware_scb, cdb32)); - } - q_hscb->tag = saved_tag; - q_hscb->next = scb->hscb->tag; - - /* Now swap HSCB pointers. */ - ahc->next_queued_scb->hscb = scb->hscb; - scb->hscb = q_hscb; - - /* Now define the mapping from tag to SCB in the scbindex */ - ahc->scb_data->scbindex[scb->hscb->tag] = scb; -} - -/* - * Tell the sequencer about a new transaction to execute. - */ -static __inline void -ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb) -{ - ahc_swap_with_next_hscb(ahc, scb); - - if (scb->hscb->tag == SCB_LIST_NULL - || scb->hscb->next == SCB_LIST_NULL) - panic("Attempt to queue invalid SCB tag %x:%x\n", - scb->hscb->tag, scb->hscb->next); - - /* - * Setup data "oddness". - */ - scb->hscb->lun &= LID; - if (ahc_get_transfer_length(scb) & 0x1) - scb->hscb->lun |= SCB_XFERLEN_ODD; - - /* - * Keep a history of SCBs we've downloaded in the qinfifo. - */ - ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag; - - /* - * Make sure our data is consistent from the - * perspective of the adapter. - */ - ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - - /* Tell the adapter about the newly queued SCB */ - if ((ahc->features & AHC_QUEUE_REGS) != 0) { - ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext); - } else { - if ((ahc->features & AHC_AUTOPAUSE) == 0) - ahc_pause(ahc); - ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext); - if ((ahc->features & AHC_AUTOPAUSE) == 0) - ahc_unpause(ahc); - } -} - -static __inline struct scsi_sense_data * +static inline struct scsi_sense_data * ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb) { int offset; @@ -493,7 +298,7 @@ return (&ahc->scb_data->sense[offset]); } -static __inline uint32_t +static inline uint32_t ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb) { int offset; @@ -504,19 +309,18 @@ } /************************** Interrupt Processing ******************************/ -static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op); -static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op); -static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc); -static __inline int ahc_intr(struct ahc_softc *ahc); +static inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op); +static inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op); +int ahc_intr(struct ahc_softc *ahc); -static __inline void +static inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op) { ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, /*offset*/0, /*len*/256, op); } -static __inline void +static inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op) { #ifdef AHC_TARGET_MODE @@ -530,120 +334,4 @@ #endif } -/* - * See if the firmware has posted any completed commands - * into our in-core command complete fifos. - */ -#define AHC_RUN_QOUTFIFO 0x1 -#define AHC_RUN_TQINFIFO 0x2 -static __inline u_int -ahc_check_cmdcmpltqueues(struct ahc_softc *ahc) -{ - u_int retval; - - retval = 0; - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap, - /*offset*/ahc->qoutfifonext, /*len*/1, - BUS_DMASYNC_POSTREAD); - if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) - retval |= AHC_RUN_QOUTFIFO; -#ifdef AHC_TARGET_MODE - if ((ahc->flags & AHC_TARGETROLE) != 0 - && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) { - ahc_dmamap_sync(ahc, ahc->shared_data_dmat, - ahc->shared_data_dmamap, - ahc_targetcmd_offset(ahc, ahc->tqinfifofnext), - /*len*/sizeof(struct target_cmd), - BUS_DMASYNC_POSTREAD); - if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0) - retval |= AHC_RUN_TQINFIFO; - } -#endif - return (retval); -} - -/* - * Catch an interrupt from the adapter - */ -static __inline int -ahc_intr(struct ahc_softc *ahc) -{ - u_int intstat; - - if ((ahc->pause & INTEN) == 0) { - /* - * Our interrupt is not enabled on the chip - * and may be disabled for re-entrancy reasons, - * so just return. This is likely just a shared - * interrupt. - */ - return (0); - } - /* - * Instead of directly reading the interrupt status register, - * infer the cause of the interrupt by checking our in-core - * completion queues. This avoids a costly PCI bus read in - * most cases. - */ - if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0 - && (ahc_check_cmdcmpltqueues(ahc) != 0)) - intstat = CMDCMPLT; - else { - intstat = ahc_inb(ahc, INTSTAT); - } - - if ((intstat & INT_PEND) == 0) { -#if AHC_PCI_CONFIG > 0 - if (ahc->unsolicited_ints > 500) { - ahc->unsolicited_ints = 0; - if ((ahc->chip & AHC_PCI) != 0 - && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0) - ahc->bus_intr(ahc); - } -#endif - ahc->unsolicited_ints++; - return (0); - } - ahc->unsolicited_ints = 0; - - if (intstat & CMDCMPLT) { - ahc_outb(ahc, CLRINT, CLRCMDINT); - - /* - * Ensure that the chip sees that we've cleared - * this interrupt before we walk the output fifo. - * Otherwise, we may, due to posted bus writes, - * clear the interrupt after we finish the scan, - * and after the sequencer has added new entries - * and asserted the interrupt again. - */ - ahc_flush_device_writes(ahc); - ahc_run_qoutfifo(ahc); -#ifdef AHC_TARGET_MODE - if ((ahc->flags & AHC_TARGETROLE) != 0) - ahc_run_tqinfifo(ahc, /*paused*/FALSE); -#endif - } - - /* - * Handle statuses that may invalidate our cached - * copy of INTSTAT separately. - */ - if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) { - /* Hot eject. Do nothing */ - } else if (intstat & BRKADRINT) { - ahc_handle_brkadrint(ahc); - } else if ((intstat & (SEQINT|SCSIINT)) != 0) { - - ahc_pause_bug_fix(ahc); - - if ((intstat & SEQINT) != 0) - ahc_handle_seqint(ahc, intstat); - - if ((intstat & SCSIINT) != 0) - ahc_handle_scsiint(ahc, intstat); - } - return (1); -} - #endif /* _AIC7XXX_INLINE_H_ */ diff -urN oldtree/drivers/scsi/aic7xxx/aic7xxx_osm.c newtree/drivers/scsi/aic7xxx/aic7xxx_osm.c --- oldtree/drivers/scsi/aic7xxx/aic7xxx_osm.c 2006-09-29 14:03:21.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic7xxx_osm.c 2006-09-29 16:13:40.000000000 -0400 @@ -328,7 +328,7 @@ * force all outstanding transactions to be serviced prior to a new * transaction. */ -uint32_t aic7xxx_periodic_otag; +static uint32_t aic7xxx_periodic_otag; /* * Module information and settable options. @@ -389,13 +389,13 @@ /********************************* Inlines ************************************/ -static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); +static inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*); -static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, +static int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len); -static __inline void +static inline void ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb) { struct scsi_cmnd *cmd; @@ -416,7 +416,7 @@ } } -static __inline int +static int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb, struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len) { @@ -490,7 +490,7 @@ return rtn; } -static inline struct scsi_target ** +static struct scsi_target ** ahc_linux_target_in_softc(struct scsi_target *starget) { struct ahc_softc *ahc = diff -urN oldtree/drivers/scsi/aic7xxx/aic7xxx_osm.h newtree/drivers/scsi/aic7xxx/aic7xxx_osm.h --- oldtree/drivers/scsi/aic7xxx/aic7xxx_osm.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic7xxx_osm.h 2006-09-29 16:13:56.000000000 -0400 @@ -231,7 +231,7 @@ #include "aic7xxx.h" /***************************** Timer Facilities *******************************/ -static __inline void +static inline void ahc_scb_timer_reset(struct scb *scb, u_int usec) { } @@ -383,82 +383,14 @@ #define malloc(size, type, flags) kmalloc(size, flags) #define free(ptr, type) kfree(ptr) -static __inline void ahc_delay(long); -static __inline void -ahc_delay(long usec) +static inline void ahc_delay(int usec) { - /* - * udelay on Linux can have problems for - * multi-millisecond waits. Wait at most - * 1024us per call. - */ - while (usec > 0) { - udelay(usec % 1024); - usec -= 1024; - } + udelay(usec); } - /***************************** Low Level I/O **********************************/ -static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port); -static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val); -static __inline void ahc_outsb(struct ahc_softc * ahc, long port, - uint8_t *, int count); -static __inline void ahc_insb(struct ahc_softc * ahc, long port, - uint8_t *, int count); - -static __inline uint8_t -ahc_inb(struct ahc_softc * ahc, long port) -{ - uint8_t x; - - if (ahc->tag == BUS_SPACE_MEMIO) { - x = readb(ahc->bsh.maddr + port); - } else { - x = inb(ahc->bsh.ioport + port); - } - mb(); - return (x); -} - -static __inline void -ahc_outb(struct ahc_softc * ahc, long port, uint8_t val) -{ - if (ahc->tag == BUS_SPACE_MEMIO) { - writeb(val, ahc->bsh.maddr + port); - } else { - outb(val, ahc->bsh.ioport + port); - } - mb(); -} - -static __inline void -ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count) -{ - int i; - - /* - * There is probably a more efficient way to do this on Linux - * but we don't use this for anything speed critical and this - * should work. - */ - for (i = 0; i < count; i++) - ahc_outb(ahc, port, *array++); -} - -static __inline void -ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count) -{ - int i; - - /* - * There is probably a more efficient way to do this on Linux - * but we don't use this for anything speed critical and this - * should work. - */ - for (i = 0; i < count; i++) - *array++ = ahc_inb(ahc, port); -} +uint8_t ahc_inb(struct ahc_softc * ahc, long port); +void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val); /**************************** Initialization **********************************/ int ahc_linux_register_host(struct ahc_softc *, @@ -478,19 +410,19 @@ /******************************** Locking *************************************/ /* Lock protecting internal data structures */ -static __inline void +static inline void ahc_lockinit(struct ahc_softc *ahc) { spin_lock_init(&ahc->platform_data->spin_lock); } -static __inline void +static inline void ahc_lock(struct ahc_softc *ahc, unsigned long *flags) { spin_lock_irqsave(&ahc->platform_data->spin_lock, *flags); } -static __inline void +static inline void ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) { spin_unlock_irqrestore(&ahc->platform_data->spin_lock, *flags); @@ -533,8 +465,6 @@ #define PCIR_SUBVEND_0 0x2c #define PCIR_SUBDEV_0 0x2e -extern struct pci_driver aic7xxx_pci_driver; - typedef enum { AHC_POWER_STATE_D0, @@ -565,10 +495,11 @@ int ahc_pci_map_registers(struct ahc_softc *ahc); int ahc_pci_map_int(struct ahc_softc *ahc); -static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci, +void ahc_BUG_bad_pci_rw_size(void); +static inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width); -static __inline uint32_t +static inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width) { switch (width) { @@ -592,17 +523,17 @@ return (retval); } default: - panic("ahc_pci_read_config: Read size too big"); + ahc_BUG_bad_pci_rw_size(); /* NOTREACHED */ return (0); } } -static __inline void ahc_pci_write_config(ahc_dev_softc_t pci, +static inline void ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width); -static __inline void +static inline void ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width) { switch (width) { @@ -616,27 +547,27 @@ pci_write_config_dword(pci, reg, value); break; default: - panic("ahc_pci_write_config: Write size too big"); + ahc_BUG_bad_pci_rw_size(); /* NOTREACHED */ } } -static __inline int ahc_get_pci_function(ahc_dev_softc_t); -static __inline int +static inline int ahc_get_pci_function(ahc_dev_softc_t); +static inline int ahc_get_pci_function(ahc_dev_softc_t pci) { return (PCI_FUNC(pci->devfn)); } -static __inline int ahc_get_pci_slot(ahc_dev_softc_t); -static __inline int +static inline int ahc_get_pci_slot(ahc_dev_softc_t); +static inline int ahc_get_pci_slot(ahc_dev_softc_t pci) { return (PCI_SLOT(pci->devfn)); } -static __inline int ahc_get_pci_bus(ahc_dev_softc_t); -static __inline int +static inline int ahc_get_pci_bus(ahc_dev_softc_t); +static inline int ahc_get_pci_bus(ahc_dev_softc_t pci) { return (pci->bus->number); @@ -649,8 +580,8 @@ } #endif -static __inline void ahc_flush_device_writes(struct ahc_softc *); -static __inline void +static inline void ahc_flush_device_writes(struct ahc_softc *); +static inline void ahc_flush_device_writes(struct ahc_softc *ahc) { /* XXX Is this sufficient for all architectures??? */ @@ -663,81 +594,81 @@ /*************************** Domain Validation ********************************/ /*********************** Transaction Access Wrappers *************************/ -static __inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t); -static __inline void ahc_set_transaction_status(struct scb *, uint32_t); -static __inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t); -static __inline void ahc_set_scsi_status(struct scb *, uint32_t); -static __inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd); -static __inline uint32_t ahc_get_transaction_status(struct scb *); -static __inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd); -static __inline uint32_t ahc_get_scsi_status(struct scb *); -static __inline void ahc_set_transaction_tag(struct scb *, int, u_int); -static __inline u_long ahc_get_transfer_length(struct scb *); -static __inline int ahc_get_transfer_dir(struct scb *); -static __inline void ahc_set_residual(struct scb *, u_long); -static __inline void ahc_set_sense_residual(struct scb *scb, u_long resid); -static __inline u_long ahc_get_residual(struct scb *); -static __inline u_long ahc_get_sense_residual(struct scb *); -static __inline int ahc_perform_autosense(struct scb *); -static __inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *, +static inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t); +static inline void ahc_set_transaction_status(struct scb *, uint32_t); +static inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t); +static inline void ahc_set_scsi_status(struct scb *, uint32_t); +static inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd); +static inline uint32_t ahc_get_transaction_status(struct scb *); +static inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd); +static inline uint32_t ahc_get_scsi_status(struct scb *); +static inline void ahc_set_transaction_tag(struct scb *, int, u_int); +static inline u_long ahc_get_transfer_length(struct scb *); +static inline int ahc_get_transfer_dir(struct scb *); +static inline void ahc_set_residual(struct scb *, u_long); +static inline void ahc_set_sense_residual(struct scb *scb, u_long resid); +static inline u_long ahc_get_residual(struct scb *); +static inline u_long ahc_get_sense_residual(struct scb *); +static inline int ahc_perform_autosense(struct scb *); +static inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *, struct scb *); -static __inline void ahc_notify_xfer_settings_change(struct ahc_softc *, +static inline void ahc_notify_xfer_settings_change(struct ahc_softc *, struct ahc_devinfo *); -static __inline void ahc_platform_scb_free(struct ahc_softc *ahc, +static inline void ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb); -static __inline void ahc_freeze_scb(struct scb *scb); +static inline void ahc_freeze_scb(struct scb *scb); -static __inline +static inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status) { cmd->result &= ~(CAM_STATUS_MASK << 16); cmd->result |= status << 16; } -static __inline +static inline void ahc_set_transaction_status(struct scb *scb, uint32_t status) { ahc_cmd_set_transaction_status(scb->io_ctx,status); } -static __inline +static inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status) { cmd->result &= ~0xFFFF; cmd->result |= status; } -static __inline +static inline void ahc_set_scsi_status(struct scb *scb, uint32_t status) { ahc_cmd_set_scsi_status(scb->io_ctx, status); } -static __inline +static inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd) { return ((cmd->result >> 16) & CAM_STATUS_MASK); } -static __inline +static inline uint32_t ahc_get_transaction_status(struct scb *scb) { return (ahc_cmd_get_transaction_status(scb->io_ctx)); } -static __inline +static inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd) { return (cmd->result & 0xFFFF); } -static __inline +static inline uint32_t ahc_get_scsi_status(struct scb *scb) { return (ahc_cmd_get_scsi_status(scb->io_ctx)); } -static __inline +static inline void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type) { /* @@ -746,43 +677,43 @@ */ } -static __inline +static inline u_long ahc_get_transfer_length(struct scb *scb) { return (scb->platform_data->xfer_len); } -static __inline +static inline int ahc_get_transfer_dir(struct scb *scb) { return (scb->io_ctx->sc_data_direction); } -static __inline +static inline void ahc_set_residual(struct scb *scb, u_long resid) { scb->io_ctx->resid = resid; } -static __inline +static inline void ahc_set_sense_residual(struct scb *scb, u_long resid) { scb->platform_data->sense_resid = resid; } -static __inline +static inline u_long ahc_get_residual(struct scb *scb) { return (scb->io_ctx->resid); } -static __inline +static inline u_long ahc_get_sense_residual(struct scb *scb) { return (scb->platform_data->sense_resid); } -static __inline +static inline int ahc_perform_autosense(struct scb *scb) { /* @@ -793,20 +724,20 @@ return (1); } -static __inline uint32_t +static inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb) { return (sizeof(struct scsi_sense_data)); } -static __inline void +static inline void ahc_notify_xfer_settings_change(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) { /* Nothing to do here for linux */ } -static __inline void +static inline void ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb) { } @@ -815,7 +746,7 @@ void ahc_platform_free(struct ahc_softc *ahc); void ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb); -static __inline void +static inline void ahc_freeze_scb(struct scb *scb) { if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) { diff -urN oldtree/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c newtree/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c --- oldtree/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c 2006-09-29 16:12:42.000000000 -0400 @@ -130,7 +130,7 @@ MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); -struct pci_driver aic7xxx_pci_driver = { +static struct pci_driver aic7xxx_pci_driver = { .name = "aic7xxx", .probe = ahc_linux_pci_dev_probe, .remove = ahc_linux_pci_dev_remove, diff -urN oldtree/drivers/scsi/aic7xxx/aic7xxx_pci.c newtree/drivers/scsi/aic7xxx/aic7xxx_pci.c --- oldtree/drivers/scsi/aic7xxx/aic7xxx_pci.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aic7xxx_pci.c 2006-09-29 16:13:40.000000000 -0400 @@ -54,7 +54,7 @@ #include "aic7xxx_pci.h" -static __inline uint64_t +static inline uint64_t ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) { uint64_t id; @@ -168,7 +168,7 @@ static ahc_device_setup_t ahc_aha494XX_setup; static ahc_device_setup_t ahc_aha398XX_setup; -struct ahc_pci_identity ahc_pci_ident_table [] = +static struct ahc_pci_identity ahc_pci_ident_table [] = { /* aic7850 based controllers */ { @@ -559,7 +559,7 @@ } }; -const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table); +static const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table); #define AHC_394X_SLOT_CHANNEL_A 4 #define AHC_394X_SLOT_CHANNEL_B 5 diff -urN oldtree/drivers/scsi/aic7xxx/aiclib.h newtree/drivers/scsi/aic7xxx/aiclib.h --- oldtree/drivers/scsi/aic7xxx/aiclib.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/aic7xxx/aiclib.h 2006-09-29 16:13:40.000000000 -0400 @@ -133,7 +133,7 @@ #define SCSI_STATUS_TASK_ABORTED 0x40 /************************* Large Disk Handling ********************************/ -static __inline int +static inline int aic_sector_div(sector_t capacity, int heads, int sectors) { /* ugly, ugly sector_div calling convention.. */ @@ -141,7 +141,7 @@ return (int)capacity; } -static __inline uint32_t +static inline uint32_t scsi_4btoul(uint8_t *bytes) { uint32_t rv; diff -urN oldtree/drivers/scsi/megaraid/megaraid_mbox.c newtree/drivers/scsi/megaraid/megaraid_mbox.c --- oldtree/drivers/scsi/megaraid/megaraid_mbox.c 2006-09-29 14:03:21.000000000 -0400 +++ newtree/drivers/scsi/megaraid/megaraid_mbox.c 2006-09-29 16:15:58.000000000 -0400 @@ -25,6 +25,7 @@ * Dell PERC3/QC 101E 1960 1028 0471 * Dell PERC3/DC 101E 1960 1028 0493 * Dell PERC3/SC 101E 1960 1028 0475 + * Dell CERC ATA100/4ch with F/W<=6.61 101E 1960 1028 0511 * Dell PERC3/Di 1028 1960 1028 0123 * Dell PERC4/SC 1000 1960 1028 0520 * Dell PERC4/DC 1000 1960 1028 0518 @@ -807,6 +808,21 @@ goto out_alloc_cmds; } + // Compatibility check + if (adapter->pdev->vendor == PCI_VENDOR_ID_AMI && + adapter->pdev->device == PCI_DEVICE_ID_AMI_MEGARAID3 && + adapter->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && + adapter->pdev->subsystem_device == PCI_SUBSYS_ID_CERC_ATA100_4CH && + (adapter->fw_version[0] > '6' || + (adapter->fw_version[0] == '6' && + adapter->fw_version[2] > '6') || + (adapter->fw_version[0] == '6' + && adapter->fw_version[2] == '6' + && adapter->fw_version[3] > '1'))) { + con_log(CL_ANN, (KERN_WARNING + "megaraid: problems? downgrade F/W to version 6.61\n")); + } + // Do we support extended CDBs adapter->max_cdb_sz = 10; if (megaraid_mbox_extended_cdb(adapter) == 0) { diff -urN oldtree/drivers/scsi/megaraid/megaraid_mbox.h newtree/drivers/scsi/megaraid/megaraid_mbox.h --- oldtree/drivers/scsi/megaraid/megaraid_mbox.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/megaraid/megaraid_mbox.h 2006-09-29 16:15:58.000000000 -0400 @@ -88,6 +88,7 @@ #define PCI_SUBSYS_ID_PERC3_QC 0x0471 #define PCI_SUBSYS_ID_PERC3_DC 0x0493 #define PCI_SUBSYS_ID_PERC3_SC 0x0475 +#define PCI_SUBSYS_ID_CERC_ATA100_4CH 0x0511 #define MBOX_MAX_SCSI_CMDS 128 // number of cmds reserved for kernel diff -urN oldtree/drivers/scsi/megaraid.c newtree/drivers/scsi/megaraid.c --- oldtree/drivers/scsi/megaraid.c 2006-09-29 14:03:21.000000000 -0400 +++ newtree/drivers/scsi/megaraid.c 2006-09-29 16:14:38.000000000 -0400 @@ -3178,7 +3178,10 @@ return len; } - +#else +static inline void mega_create_proc_entry(int index, struct proc_dir_entry *parent) +{ +} #endif @@ -4343,7 +4346,7 @@ return 0; } - +#ifdef CONFIG_PROC_FS /** * mega_adapinq() * @adapter - pointer to our soft state @@ -4448,7 +4451,7 @@ return rval; } - +#endif /** * mega_internal_command() @@ -4964,7 +4967,6 @@ { struct Scsi_Host *host = pci_get_drvdata(pdev); adapter_t *adapter = (adapter_t *)host->hostdata; - char buf[12] = { 0 }; scsi_remove_host(host); @@ -5010,8 +5012,11 @@ remove_proc_entry("raiddrives-30-39", adapter->controller_proc_dir_entry); #endif - sprintf(buf, "hba%d", adapter->host->host_no); - remove_proc_entry(buf, mega_proc_dir_entry); + { + char buf[12] = { 0 }; + sprintf(buf, "hba%d", adapter->host->host_no); + remove_proc_entry(buf, mega_proc_dir_entry); + } } #endif diff -urN oldtree/drivers/scsi/megaraid.h newtree/drivers/scsi/megaraid.h --- oldtree/drivers/scsi/megaraid.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/megaraid.h 2006-09-29 16:14:38.000000000 -0400 @@ -1001,7 +1001,6 @@ static int megaraid_abort_and_reset(adapter_t *, Scsi_Cmnd *, int); static int megaraid_biosparam(struct scsi_device *, struct block_device *, sector_t, int []); -static int mega_print_inquiry(char *, char *); static int mega_build_sglist (adapter_t *adapter, scb_t *scb, u32 *buffer, u32 *length); @@ -1023,6 +1022,7 @@ static int mega_is_bios_enabled (adapter_t *); #ifdef CONFIG_PROC_FS +static int mega_print_inquiry(char *, char *); static void mega_create_proc_entry(int, struct proc_dir_entry *); static int proc_read_config(char *, char **, off_t, int, int *, void *); static int proc_read_stat(char *, char **, off_t, int, int *, void *); @@ -1039,10 +1039,10 @@ static int proc_rdrv_30(char *, char **, off_t, int, int *, void *); static int proc_rdrv_40(char *, char **, off_t, int, int *, void *); static int proc_rdrv(adapter_t *, char *, int, int); -#endif static int mega_adapinq(adapter_t *, dma_addr_t); static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t); +#endif static int mega_support_ext_cdb(adapter_t *); static mega_passthru* mega_prepare_passthru(adapter_t *, scb_t *, diff -urN oldtree/drivers/scsi/pcmcia/nsp_cs.h newtree/drivers/scsi/pcmcia/nsp_cs.h --- oldtree/drivers/scsi/pcmcia/nsp_cs.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/pcmcia/nsp_cs.h 2006-09-29 16:15:00.000000000 -0400 @@ -290,7 +290,6 @@ #endif } nsp_hw_data; - /**************************************************************************** * */ @@ -302,22 +301,13 @@ /* Linux SCSI subsystem specific functions */ static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -static int nsp_detect_old (struct scsi_host_template *sht); -static int nsp_release_old(struct Scsi_Host *shpnt); -#endif static const char *nsp_info (struct Scsi_Host *shpnt); static int nsp_proc_info ( -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) struct Scsi_Host *host, -#endif char *buffer, char **start, off_t offset, int length, -#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) - int hostno, -#endif int inout); static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (* done)(Scsi_Cmnd *SCpnt)); @@ -352,7 +342,6 @@ static int __init nsp_cs_init(void); static void __exit nsp_cs_exit(void); - /* Debug */ #ifdef NSP_DEBUG static void show_command (Scsi_Cmnd *SCpnt); @@ -397,7 +386,6 @@ BURST_MEM32 = 2, }; - /************************************************************************** * SCSI messaage */ @@ -409,62 +397,8 @@ #define MSG_EXT_SDTR 0x01 - -/************************************************************************** - * Compatibility functions - */ - -/* for Kernel 2.4 */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) -# define scsi_register_host(template) scsi_register_module(MODULE_SCSI_HA, template) -# define scsi_unregister_host(template) scsi_unregister_module(MODULE_SCSI_HA, template) -# define scsi_host_put(host) scsi_unregister(host) - -typedef void irqreturn_t; -# define IRQ_NONE /* */ -# define IRQ_HANDLED /* */ -# define IRQ_RETVAL(x) /* */ - -/* This is ad-hoc version of scsi_host_get_next() */ -static inline struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *host) -{ - if (host == NULL) { - return scsi_hostlist; - } else { - return host->next; - } -} - -/* This is ad-hoc version of scsi_host_hn_get() */ -static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno) -{ - struct Scsi_Host *host; - - for (host = scsi_host_get_next(NULL); host != NULL; - host = scsi_host_get_next(host)) { - if (host->host_no == hostno) { - break; - } - } - - return host; -} - -static void cs_error(struct pcmcia_device *handle, int func, int ret) -{ - error_info_t err = { func, ret }; - pcmcia_report_error(handle, &err); -} - -/* scatter-gather table */ -# define BUFFER_ADDR (SCpnt->SCp.buffer->address) -#endif - -/* for Kernel 2.6 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) /* scatter-gather table */ # define BUFFER_ADDR ((char *)((unsigned int)(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset)) -#endif #endif /*__nsp_cs__*/ /* end */ diff -urN oldtree/drivers/scsi/qla2xxx/qla_os.c newtree/drivers/scsi/qla2xxx/qla_os.c --- oldtree/drivers/scsi/qla2xxx/qla_os.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/qla2xxx/qla_os.c 2006-09-29 16:12:58.000000000 -0400 @@ -274,7 +274,7 @@ return str; } -char * +static char * qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str) { char un_str[10]; @@ -312,7 +312,7 @@ return (str); } -char * +static char * qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str) { sprintf(str, "%d.%02d.%02d ", ha->fw_major_version, @@ -604,7 +604,7 @@ * Note: * Only return FAILED if command not returned by firmware. **************************************************************************/ -int +static int qla2xxx_eh_abort(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -739,7 +739,7 @@ * SUCCESS/FAILURE (defined as macro in scsi.h). * **************************************************************************/ -int +static int qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -868,7 +868,7 @@ * SUCCESS/FAILURE (defined as macro in scsi.h). * **************************************************************************/ -int +static int qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -927,7 +927,7 @@ * * Note: **************************************************************************/ -int +static int qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); diff -urN oldtree/drivers/scsi/qla2xxx/qla_sup.c newtree/drivers/scsi/qla2xxx/qla_sup.c --- oldtree/drivers/scsi/qla2xxx/qla_sup.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/qla2xxx/qla_sup.c 2006-09-29 16:12:58.000000000 -0400 @@ -449,7 +449,7 @@ return FARX_ACCESS_NVRAM_DATA | naddr; } -uint32_t +static uint32_t qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr) { int rval; @@ -490,7 +490,7 @@ return dwptr; } -int +static int qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data) { int rval; @@ -512,7 +512,7 @@ return rval; } -void +static void qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, uint8_t *flash_id) { @@ -537,7 +537,7 @@ } } -int +static int qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { diff -urN oldtree/drivers/scsi/scsi.c newtree/drivers/scsi/scsi.c --- oldtree/drivers/scsi/scsi.c 2006-09-29 14:03:21.000000000 -0400 +++ newtree/drivers/scsi/scsi.c 2006-09-29 16:15:51.000000000 -0400 @@ -128,7 +128,7 @@ return "Well-known LUN "; if (type == 0x1f) return "No Device "; - if (type > ARRAY_SIZE(scsi_device_types)) + if (type >= ARRAY_SIZE(scsi_device_types)) return "Unknown "; return scsi_device_types[type]; } diff -urN oldtree/drivers/scsi/scsi_sysctl.c newtree/drivers/scsi/scsi_sysctl.c --- oldtree/drivers/scsi/scsi_sysctl.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/scsi_sysctl.c 2006-09-29 16:12:49.000000000 -0400 @@ -9,6 +9,7 @@ #include #include "scsi_logging.h" +#include "scsi_priv.h" static ctl_table scsi_table[] = { diff -urN oldtree/drivers/scsi/scsi_sysfs.c newtree/drivers/scsi/scsi_sysfs.c --- oldtree/drivers/scsi/scsi_sysfs.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/scsi_sysfs.c 2006-09-29 16:12:49.000000000 -0400 @@ -16,6 +16,7 @@ #include #include #include +#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -762,7 +763,7 @@ } EXPORT_SYMBOL(scsi_remove_device); -void __scsi_remove_target(struct scsi_target *starget) +static void __scsi_remove_target(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; diff -urN oldtree/drivers/scsi/scsi_transport_fc.c newtree/drivers/scsi/scsi_transport_fc.c --- oldtree/drivers/scsi/scsi_transport_fc.c 2006-09-29 14:03:21.000000000 -0400 +++ newtree/drivers/scsi/scsi_transport_fc.c 2006-09-29 16:12:49.000000000 -0400 @@ -1797,7 +1797,7 @@ * Notes: * This routine assumes no locks are held on entry. **/ -struct fc_rport * +static struct fc_rport * fc_rport_create(struct Scsi_Host *shost, int channel, struct fc_rport_identifiers *ids) { diff -urN oldtree/drivers/scsi/sg.c newtree/drivers/scsi/sg.c --- oldtree/drivers/scsi/sg.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/sg.c 2006-09-29 16:15:24.000000000 -0400 @@ -1828,7 +1828,7 @@ int blk_size = buff_size; struct page *p = NULL; - if ((blk_size < 0) || (!sfp)) + if (blk_size < 0) return -EFAULT; if (0 == blk_size) ++blk_size; /* don't know why */ diff -urN oldtree/drivers/scsi/sr.c newtree/drivers/scsi/sr.c --- oldtree/drivers/scsi/sr.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/sr.c 2006-09-29 16:12:49.000000000 -0400 @@ -174,7 +174,7 @@ * an inode for that to work, and we do not always have one. */ -int sr_media_change(struct cdrom_device_info *cdi, int slot) +static int sr_media_change(struct cdrom_device_info *cdi, int slot) { struct scsi_cd *cd = cdi->handle; int retval; diff -urN oldtree/drivers/scsi/sym53c8xx_2/sym_glue.c newtree/drivers/scsi/sym53c8xx_2/sym_glue.c --- oldtree/drivers/scsi/sym53c8xx_2/sym_glue.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/sym53c8xx_2/sym_glue.c 2006-09-29 16:15:08.000000000 -0400 @@ -659,6 +659,11 @@ if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("["); + /* Avoid spinloop trying to handle interrupts on frozen device */ + if ((np->s.device->error_state != pci_channel_io_normal) && + (np->s.device->error_state != 0)) + return IRQ_HANDLED; + spin_lock_irqsave(np->s.host->host_lock, flags); sym_interrupt(np); spin_unlock_irqrestore(np->s.host->host_lock, flags); @@ -726,6 +731,19 @@ dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname); + /* We may be in an error condition because the PCI bus + * went down. In this case, we need to wait until the + * PCI bus is reset, the card is reset, and only then + * proceed with the scsi error recovery. There's no + * point in hurrying; take a leisurely wait. + */ +#define WAIT_FOR_PCI_RECOVERY 35 + if ((np->s.device->error_state != pci_channel_io_normal) && + (np->s.device->error_state != 0) && + (wait_for_completion_timeout(&np->s.io_reset_wait, + WAIT_FOR_PCI_RECOVERY*HZ) == 0)) + return SCSI_FAILED; + spin_lock_irq(host->host_lock); /* This one is queued in some place -> to wait for completion */ FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) { @@ -1510,6 +1528,7 @@ np->maxoffs = dev->chip.offset_max; np->maxburst = dev->chip.burst_max; np->myaddr = dev->host_id; + init_completion(&np->s.io_reset_wait); /* * Edit its name. @@ -1948,6 +1967,79 @@ attach_count--; } +/** + * sym2_io_error_detected() -- called when PCI error is detected + * @pdev: pointer to PCI device + * @state: current state of the PCI slot + */ +static pci_ers_result_t sym2_io_error_detected (struct pci_dev *pdev, + enum pci_channel_state state) +{ + struct sym_hcb *np = pci_get_drvdata(pdev); + + /* If slot is permanently frozen, turn everything off */ + if (state == pci_channel_io_perm_failure) { + sym2_remove(pdev); + return PCI_ERS_RESULT_DISCONNECT; + } + + init_completion(&np->s.io_reset_wait); + disable_irq(pdev->irq); + pci_disable_device(pdev); + + /* Request a slot reset. */ + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * sym2_io_slot_reset() -- called when the pci bus has been reset. + * @pdev: pointer to PCI device + * + * Restart the card from scratch. + */ +static pci_ers_result_t sym2_io_slot_reset (struct pci_dev *pdev) +{ + struct sym_hcb *np = pci_get_drvdata(pdev); + + printk(KERN_INFO "%s: recovering from a PCI slot reset\n", + sym_name(np)); + + if (pci_enable_device(pdev)) { + printk(KERN_ERR "%s: device setup failed most egregiously\n", + sym_name(np)); + return PCI_ERS_RESULT_DISCONNECT; + } + + pci_set_master(pdev); + enable_irq(pdev->irq); + + /* Perform host reset only on one instance of the card */ + if (PCI_FUNC (pdev->devfn) == 0) { + if (sym_reset_scsi_bus(np, 0)) { + printk(KERN_ERR "%s: Unable to reset scsi host controller\n", + sym_name(np)); + return PCI_ERS_RESULT_DISCONNECT; + } + sym_start_up(np, 1); + } + + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * sym2_io_resume() -- resume normal ops after PCI reset + * @pdev: pointer to PCI device + * + * Called when the error recovery driver tells us that its + * OK to resume normal operation. Use completion to allow + * halted scsi ops to resume. + */ +static void sym2_io_resume (struct pci_dev *pdev) +{ + struct sym_hcb *np = pci_get_drvdata(pdev); + complete_all(&np->s.io_reset_wait); +} + static void sym2_get_signalling(struct Scsi_Host *shost) { struct sym_hcb *np = sym_get_hcb(shost); @@ -2110,11 +2202,18 @@ MODULE_DEVICE_TABLE(pci, sym2_id_table); +static struct pci_error_handlers sym2_err_handler = { + .error_detected = sym2_io_error_detected, + .slot_reset = sym2_io_slot_reset, + .resume = sym2_io_resume, +}; + static struct pci_driver sym2_driver = { .name = NAME53C8XX, .id_table = sym2_id_table, .probe = sym2_probe, .remove = __devexit_p(sym2_remove), + .err_handler = &sym2_err_handler, }; static int __init sym2_init(void) diff -urN oldtree/drivers/scsi/sym53c8xx_2/sym_glue.h newtree/drivers/scsi/sym53c8xx_2/sym_glue.h --- oldtree/drivers/scsi/sym53c8xx_2/sym_glue.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/sym53c8xx_2/sym_glue.h 2006-09-29 16:15:08.000000000 -0400 @@ -40,6 +40,7 @@ #ifndef SYM_GLUE_H #define SYM_GLUE_H +#include #include #include #include @@ -179,6 +180,9 @@ char chip_name[8]; struct pci_dev *device; + /* Waiter for clearing of frozen PCI bus */ + struct completion io_reset_wait; + struct Scsi_Host *host; void __iomem * ioaddr; /* MMIO kernel io address */ diff -urN oldtree/drivers/scsi/sym53c8xx_2/sym_hipd.c newtree/drivers/scsi/sym53c8xx_2/sym_hipd.c --- oldtree/drivers/scsi/sym53c8xx_2/sym_hipd.c 2006-09-29 13:50:42.000000000 -0400 +++ newtree/drivers/scsi/sym53c8xx_2/sym_hipd.c 2006-09-29 16:15:08.000000000 -0400 @@ -2761,6 +2761,7 @@ u_char istat, istatc; u_char dstat; u_short sist; + u_int icnt; /* * interrupt on the fly ? @@ -2802,6 +2803,7 @@ sist = 0; dstat = 0; istatc = istat; + icnt = 0; do { if (istatc & SIP) sist |= INW(np, nc_sist); @@ -2809,6 +2811,14 @@ dstat |= INB(np, nc_dstat); istatc = INB(np, nc_istat); istat |= istatc; + + /* Prevent deadlock waiting on a condition that may never clear. */ + icnt ++; + if (icnt > 100) { + if ((np->s.device->error_state != pci_channel_io_normal) + && (np->s.device->error_state != 0)) + return; + } } while (istatc & (SIP|DIP)); if (DEBUG_FLAGS & DEBUG_TINY) diff -urN oldtree/include/scsi/scsi_transport.h newtree/include/scsi/scsi_transport.h --- oldtree/include/scsi/scsi_transport.h 2006-09-29 13:50:42.000000000 -0400 +++ newtree/include/scsi/scsi_transport.h 2006-09-29 16:15:47.000000000 -0400 @@ -22,6 +22,7 @@ #include #include +#include struct scsi_transport_template { /* the attribute containers */