diff options
Diffstat (limited to 'drivers/scsi')
124 files changed, 21248 insertions, 17497 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 76c09097175..efd9d8d3a89 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -4,7 +4,7 @@ Written By: Adam Radford <linuxraid@amcc.com> Modifications By: Tom Couch <linuxraid@amcc.com> - Copyright (C) 2004-2006 Applied Micro Circuits Corporation. + Copyright (C) 2004-2007 Applied Micro Circuits Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -69,6 +69,8 @@ 2.26.02.008 - Free irq handler in __twa_shutdown(). Serialize reset code. Add support for 9650SE controllers. + 2.26.02.009 - Fix dma mask setting to fallback to 32-bit if 64-bit fails. + 2.26.02.010 - Add support for 9690SA controllers. */ #include <linux/module.h> @@ -92,7 +94,7 @@ #include "3w-9xxx.h" /* Globals */ -#define TW_DRIVER_VERSION "2.26.02.008" +#define TW_DRIVER_VERSION "2.26.02.010" static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static unsigned int twa_device_extension_count; static int twa_major = -1; @@ -124,11 +126,11 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits, unsigned short *fw_on_ctlr_branch, unsigned short *fw_on_ctlr_build, u32 *init_connect_result); -static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); +static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length); static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds); static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds); static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); -static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset); +static int twa_reset_device_extension(TW_Device_Extension *tw_dev); static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); @@ -683,7 +685,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int full_command_packet = &tw_ioctl->firmware_command; /* Load request id and sglist for both command types */ - twa_load_sgl(full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); + twa_load_sgl(tw_dev, full_command_packet, request_id, dma_handle, data_buffer_length_adjusted); memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full)); @@ -700,10 +702,10 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { /* Now we need to reset the board */ printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n", - tw_dev->host->host_no, TW_DRIVER, 0xc, + tw_dev->host->host_no, TW_DRIVER, 0x37, cmd); retval = TW_IOCTL_ERROR_OS_EIO; - twa_reset_device_extension(tw_dev, 1); + twa_reset_device_extension(tw_dev); goto out3; } @@ -890,7 +892,9 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) } if (status_reg_value & TW_STATUS_QUEUE_ERROR) { - if ((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) || (!test_bit(TW_IN_RESET, &tw_dev->flags))) + if (((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) && + (tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9690SA)) || + (!test_bit(TW_IN_RESET, &tw_dev->flags))) TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); } @@ -935,8 +939,7 @@ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) unsigned long before; int retval = 1; - if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) || - (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) { + if (tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9000) { before = jiffies; while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); @@ -1160,13 +1163,12 @@ static int twa_initialize_device_extension(TW_Device_Extension *tw_dev) } /* Allocate event info space */ - tw_dev->event_queue[0] = kmalloc(sizeof(TW_Event) * TW_Q_LENGTH, GFP_KERNEL); + tw_dev->event_queue[0] = kcalloc(TW_Q_LENGTH, sizeof(TW_Event), GFP_KERNEL); if (!tw_dev->event_queue[0]) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x18, "Event info memory allocation failed"); goto out; } - memset(tw_dev->event_queue[0], 0, sizeof(TW_Event) * TW_Q_LENGTH); for (i = 0; i < TW_Q_LENGTH; i++) { tw_dev->event_queue[i] = (TW_Event *)((unsigned char *)tw_dev->event_queue[0] + (i * sizeof(TW_Event))); @@ -1196,7 +1198,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) u32 status_reg_value; TW_Response_Queue response_que; TW_Command_Full *full_command_packet; - TW_Command *command_packet; TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; int handled = 0; @@ -1274,7 +1275,6 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) request_id = TW_RESID_OUT(response_que.response_id); full_command_packet = tw_dev->command_packet_virt[request_id]; error = 0; - command_packet = &full_command_packet->command.oldcommand; /* Check for command packet errors */ if (full_command_packet->command.newcommand.status != 0) { if (tw_dev->srb[request_id] != 0) { @@ -1353,11 +1353,15 @@ twa_interrupt_bail: } /* End twa_interrupt() */ /* This function will load the request id and various sgls for ioctls */ -static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) +static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length) { TW_Command *oldcommand; TW_Command_Apache *newcommand; TW_SG_Entry *sgl; + unsigned int pae = 0; + + if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) + pae = 1; if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { newcommand = &full_command_packet->command.newcommand; @@ -1373,12 +1377,14 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) { /* Load the sg list */ - sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); + if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA) + sgl = (TW_SG_Entry *)((u32 *)oldcommand+oldcommand->size - (sizeof(TW_SG_Entry)/4) + pae); + else + sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset)); sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); sgl->length = cpu_to_le32(length); - if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4)) - oldcommand->size += 1; + oldcommand->size += pae; } } } /* End twa_load_sgl() */ @@ -1507,7 +1513,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, command_que_value = tw_dev->command_packet_phys[request_id]; /* For 9650SE write low 4 bytes first */ - if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { + if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) || + (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) { command_que_value += TW_COMMAND_OFFSET; writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); } @@ -1538,7 +1545,8 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, TW_UNMASK_COMMAND_INTERRUPT(tw_dev); goto out; } else { - if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { + if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) || + (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9690SA)) { /* Now write upper 4 bytes */ writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); } else { @@ -1562,7 +1570,7 @@ out: } /* End twa_post_command_packet() */ /* This function will reset a device extension */ -static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset) +static int twa_reset_device_extension(TW_Device_Extension *tw_dev) { int i = 0; int retval = 1; @@ -1720,7 +1728,7 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt) mutex_lock(&tw_dev->ioctl_lock); /* Now reset the card and some of the device extension data */ - if (twa_reset_device_extension(tw_dev, 0)) { + if (twa_reset_device_extension(tw_dev)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); goto out; } @@ -2002,11 +2010,14 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id pci_set_master(pdev); - retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK); - if (retval) { - TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); - goto out_disable_device; - } + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) + || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) + || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask"); + retval = -ENODEV; + goto out_disable_device; + } host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension)); if (!host) { @@ -2054,7 +2065,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id goto out_iounmap; /* Set host specific parameters */ - if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE) + if ((pdev->device == PCI_DEVICE_ID_3WARE_9650SE) || + (pdev->device == PCI_DEVICE_ID_3WARE_9690SA)) host->max_id = TW_MAX_UNITS_9650SE; else host->max_id = TW_MAX_UNITS; @@ -2161,6 +2173,8 @@ static struct pci_device_id twa_pci_tbl[] __devinitdata = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9690SA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { } }; MODULE_DEVICE_TABLE(pci, twa_pci_tbl); diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index 7901517d451..d14a9479e38 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h @@ -4,7 +4,7 @@ Written By: Adam Radford <linuxraid@amcc.com> Modifications By: Tom Couch <linuxraid@amcc.com> - Copyright (C) 2004-2006 Applied Micro Circuits Corporation. + Copyright (C) 2004-2007 Applied Micro Circuits Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -419,6 +419,9 @@ static twa_message_type twa_error_table[] = { #ifndef PCI_DEVICE_ID_3WARE_9650SE #define PCI_DEVICE_ID_3WARE_9650SE 0x1004 #endif +#ifndef PCI_DEVICE_ID_3WARE_9690SA +#define PCI_DEVICE_ID_3WARE_9690SA 0x1005 +#endif /* Bitmask macros to eliminate bitfields */ diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 372723161c9..6f2c71ef47e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -282,7 +282,7 @@ config SCSI_ISCSI_ATTRS config SCSI_SAS_ATTRS tristate "SAS Transport Attributes" - depends on SCSI + depends on SCSI && BLK_DEV_BSG help If you wish to export transport-specific information about each attached SAS device to sysfs, say Y. @@ -291,8 +291,12 @@ source "drivers/scsi/libsas/Kconfig" endmenu -menu "SCSI low-level drivers" +menuconfig SCSI_LOWLEVEL + bool "SCSI low-level drivers" depends on SCSI!=n + default y + +if SCSI_LOWLEVEL config ISCSI_TCP tristate "iSCSI Initiator over TCP/IP" @@ -363,6 +367,7 @@ config SCSI_3W_9XXX config SCSI_7000FASST tristate "7000FASST SCSI support" depends on ISA && SCSI && ISA_DMA_API + select CHECK_SIGNATURE help This driver supports the Western Digital 7000 SCSI host adapter family. Some information is in the source: @@ -384,6 +389,7 @@ config SCSI_AHA152X tristate "Adaptec AHA152X/2825 support" depends on ISA && SCSI && !64BIT select SCSI_SPI_ATTRS + select CHECK_SIGNATURE ---help--- This is a driver for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825 SCSI host adapters. It also works for the AVA-1505, but the IRQ etc. @@ -483,7 +489,7 @@ source "drivers/scsi/aic94xx/Kconfig" # All the I2O code and drivers do not seem to be 64bit safe. config SCSI_DPT_I2O tristate "Adaptec I2O RAID support " - depends on !64BIT && SCSI && PCI + depends on !64BIT && SCSI && PCI && VIRT_TO_BUS help This driver supports all of Adaptec's I2O based RAID controllers as well as the DPT SmartRaid V cards. This is an Adaptec maintained @@ -579,6 +585,7 @@ config SCSI_DTC3280 tristate "DTC3180/3280 SCSI support" depends on ISA && SCSI select SCSI_SPI_ATTRS + select CHECK_SIGNATURE help This is support for DTC 3180/3280 SCSI Host Adapters. Please read the SCSI-HOWTO, available from @@ -653,6 +660,7 @@ config SCSI_EATA_PIO config SCSI_FUTURE_DOMAIN tristate "Future Domain 16xx SCSI/AHA-2920A support" depends on (ISA || PCI) && SCSI + select CHECK_SIGNATURE ---help--- This is support for Future Domain's 16-bit SCSI host adapters (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and @@ -1320,6 +1328,7 @@ config SCSI_LPFC config SCSI_SEAGATE tristate "Seagate ST-02 and Future Domain TMC-8xx SCSI support" depends on X86 && ISA && SCSI + select CHECK_SIGNATURE ---help--- These are 8-bit SCSI controllers; the ST-01 is also supported by this driver. It is explained in section 3.9 of the SCSI-HOWTO, @@ -1393,6 +1402,7 @@ config SCSI_T128 tristate "Trantor T128/T128F/T228 SCSI support" depends on ISA && SCSI select SCSI_SPI_ATTRS + select CHECK_SIGNATURE ---help--- This is support for a SCSI host adapter. It is explained in section 3.11 of the SCSI-HOWTO, available from @@ -1557,7 +1567,7 @@ config A3000_SCSI built-in SCSI controller, say Y. Otherwise, say N. To compile this driver as a module, choose M here: the - module will be called wd33c93. + module will be called a3000. config A2091_SCSI tristate "A2091/A590 WD33C93A support" @@ -1567,7 +1577,7 @@ config A2091_SCSI say N. To compile this driver as a module, choose M here: the - module will be called wd33c93. + module will be called a2091. config GVP11_SCSI tristate "GVP Series II WD33C93A support" @@ -1800,7 +1810,7 @@ config SCSI_SRP To compile this driver as a module, choose M here: the module will be called libsrp. -endmenu +endif # SCSI_LOWLEVEL source "drivers/scsi/pcmcia/Kconfig" diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 0f868955715..86a7ba7bad6 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -132,6 +132,7 @@ obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/ obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o obj-$(CONFIG_SCSI_STEX) += stex.o +obj-$(CONFIG_PS3_ROM) += ps3rom.o obj-$(CONFIG_ARM) += arm/ diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index 8b5334c56f0..79b4df15814 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -95,6 +95,8 @@ enum { /* The master ring of all esp hosts we are managing in this driver. */ static struct NCR_ESP *espchain; int nesps = 0, esps_in_use = 0, esps_running = 0; +EXPORT_SYMBOL(nesps); +EXPORT_SYMBOL(esps_running); irqreturn_t esp_intr(int irq, void *dev_id); @@ -524,6 +526,7 @@ void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs) /* Eat any bitrot in the chip and we are done... */ trash = esp_read(eregs->esp_intrpt); } +EXPORT_SYMBOL(esp_bootup_reset); /* Allocate structure and insert basic data such as SCSI chip frequency * data and a pointer to the device @@ -772,6 +775,7 @@ const char *esp_info(struct Scsi_Host *host) panic("Bogon ESP revision"); }; } +EXPORT_SYMBOL(esp_info); /* From Wolfgang Stanglmeier's NCR scsi driver. */ struct info_str @@ -902,6 +906,7 @@ int esp_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t off *start = buffer; return esp_host_info(esp, buffer, offset, length); } +EXPORT_SYMBOL(esp_proc_info); static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp) { @@ -3535,6 +3540,7 @@ state_machine: if(esp->dma_irq_exit) esp->dma_irq_exit(esp); } +EXPORT_SYMBOL(esp_handle); #ifndef CONFIG_SMP irqreturn_t esp_intr(int irq, void *dev_id) @@ -3606,11 +3612,10 @@ out: int esp_slave_alloc(struct scsi_device *SDptr) { struct esp_device *esp_dev = - kmalloc(sizeof(struct esp_device), GFP_ATOMIC); + kzalloc(sizeof(struct esp_device), GFP_ATOMIC); if (!esp_dev) return -ENOMEM; - memset(esp_dev, 0, sizeof(struct esp_device)); SDptr->hostdata = esp_dev; return 0; } @@ -3632,6 +3637,7 @@ void esp_release(void) esps_in_use--; esps_running = esps_in_use; } +EXPORT_SYMBOL(esp_release); #endif EXPORT_SYMBOL(esp_abort); diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c index f12864abed2..3a8089705fe 100644 --- a/drivers/scsi/NCR_D700.c +++ b/drivers/scsi/NCR_D700.c @@ -181,13 +181,12 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq, struct Scsi_Host *host; int ret; - hostdata = kmalloc(sizeof(*hostdata), GFP_KERNEL); + hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); if (!hostdata) { printk(KERN_ERR "NCR D700: SIOP%d: Failed to allocate host" "data, detatching\n", siop); return -ENOMEM; } - memset(hostdata, 0, sizeof(*hostdata)); if (!request_region(region, 64, "NCR_D700")) { printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n", diff --git a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c index 778844c3544..a8bbdc2273b 100644 --- a/drivers/scsi/NCR_Q720.c +++ b/drivers/scsi/NCR_Q720.c @@ -148,11 +148,10 @@ NCR_Q720_probe(struct device *dev) __u32 base_addr, mem_size; void __iomem *mem_base; - p = kmalloc(sizeof(*p), GFP_KERNEL); + p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; - memset(p, 0, sizeof(*p)); pos2 = mca_device_read_pos(mca_dev, 2); /* enable device */ pos2 |= NCR_Q720_POS2_BOARD_ENABLE | NCR_Q720_POS2_INTERRUPT_ENABLE; diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 6a5784683ed..0c758d1452b 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c @@ -79,6 +79,7 @@ static int __devinit a4000t_probe(struct device *dev) goto out_put_host; } + dev_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -95,7 +96,7 @@ static int __devinit a4000t_probe(struct device *dev) static __devexit int a4000t_device_remove(struct device *dev) { - struct Scsi_Host *host = dev_to_shost(dev); + struct Scsi_Host *host = dev_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); scsi_remove_host(host); diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 0b6fd0b654d..6800e578e4b 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -194,8 +194,7 @@ static inline int aac_valid_context(struct scsi_cmnd *scsicmd, struct scsi_device *device; if (unlikely(!scsicmd || !scsicmd->scsi_done )) { - dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n")) -; + dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n")); aac_fib_complete(fibptr); aac_fib_free(fibptr); return 0; @@ -751,6 +750,101 @@ static void setinqstr(struct aac_dev *dev, void *data, int tindex) inqstrcpy ("V1.0", str->prl); } +static void get_container_serial_callback(void *context, struct fib * fibptr) +{ + struct aac_get_serial_resp * get_serial_reply; + struct scsi_cmnd * scsicmd; + + BUG_ON(fibptr == NULL); + + scsicmd = (struct scsi_cmnd *) context; + if (!aac_valid_context(scsicmd, fibptr)) + return; + + get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); + /* Failure is irrelevant, using default value instead */ + if (le32_to_cpu(get_serial_reply->status) == CT_OK) { + char sp[13]; + /* EVPD bit set */ + sp[0] = INQD_PDT_DA; + sp[1] = scsicmd->cmnd[2]; + sp[2] = 0; + sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", + le32_to_cpu(get_serial_reply->uid)); + aac_internal_transfer(scsicmd, sp, 0, sizeof(sp)); + } + + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + scsicmd->scsi_done(scsicmd); +} + +/** + * aac_get_container_serial - get container serial, none blocking. + */ +static int aac_get_container_serial(struct scsi_cmnd * scsicmd) +{ + int status; + struct aac_get_serial *dinfo; + struct fib * cmd_fibcontext; + struct aac_dev * dev; + + dev = (struct aac_dev *)scsicmd->device->host->hostdata; + + if (!(cmd_fibcontext = aac_fib_alloc(dev))) + return -ENOMEM; + + aac_fib_init(cmd_fibcontext); + dinfo = (struct aac_get_serial *) fib_data(cmd_fibcontext); + + dinfo->command = cpu_to_le32(VM_ContainerConfig); + dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID); + dinfo->cid = cpu_to_le32(scmd_id(scsicmd)); + + status = aac_fib_send(ContainerCommand, + cmd_fibcontext, + sizeof (struct aac_get_serial), + FsaNormal, + 0, 1, + (fib_callback) get_container_serial_callback, + (void *) scsicmd); + + /* + * Check that the command queued to the controller + */ + if (status == -EINPROGRESS) { + scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; + return 0; + } + + printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status); + aac_fib_complete(cmd_fibcontext); + aac_fib_free(cmd_fibcontext); + return -1; +} + +/* Function: setinqserial + * + * Arguments: [1] pointer to void [1] int + * + * Purpose: Sets SCSI Unit Serial number. + * This is a fake. We should read a proper + * serial number from the container. <SuSE>But + * without docs it's quite hard to do it :-) + * So this will have to do in the meantime.</SuSE> + */ + +static int setinqserial(struct aac_dev *dev, void *data, int cid) +{ + /* + * This breaks array migration. + */ + return snprintf((char *)(data), sizeof(struct scsi_inq) - 4, "%08X%02X", + le32_to_cpu(dev->adapter_info.serial[0]), cid); +} + static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code, u8 a_sense_code, u8 incorrect_length, u8 bit_pointer, u16 field_pointer, @@ -1594,23 +1688,23 @@ static void synchronize_callback(void *context, struct fib *fibptr) if (!aac_valid_context(cmd, fibptr)) return; - dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", + dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); BUG_ON(fibptr == NULL); synchronizereply = fib_data(fibptr); if (le32_to_cpu(synchronizereply->status) == CT_OK) - cmd->result = DID_OK << 16 | + cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; else { struct scsi_device *sdev = cmd->device; struct aac_dev *dev = fibptr->dev; u32 cid = sdev_id(sdev); - printk(KERN_WARNING + printk(KERN_WARNING "synchronize_callback: synchronize failed, status = %d\n", le32_to_cpu(synchronizereply->status)); - cmd->result = DID_OK << 16 | + cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; set_sense((u8 *)&dev->fsa_dev[cid].sense_data, HARDWARE_ERROR, @@ -1618,7 +1712,7 @@ static void synchronize_callback(void *context, struct fib *fibptr) ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, 0, 0); memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data, - min(sizeof(dev->fsa_dev[cid].sense_data), + min(sizeof(dev->fsa_dev[cid].sense_data), sizeof(cmd->sense_buffer))); } @@ -1636,6 +1730,9 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) struct scsi_device *sdev = scsicmd->device; int active = 0; struct aac_dev *aac; + u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | + (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; + u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; unsigned long flags; /* @@ -1644,7 +1741,51 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) */ spin_lock_irqsave(&sdev->list_lock, flags); list_for_each_entry(cmd, &sdev->cmd_list, list) - if (cmd != scsicmd && cmd->SCp.phase == AAC_OWNER_FIRMWARE) { + if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) { + u64 cmnd_lba; + u32 cmnd_count; + + if (cmd->cmnd[0] == WRITE_6) { + cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) | + (cmd->cmnd[2] << 8) | + cmd->cmnd[3]; + cmnd_count = cmd->cmnd[4]; + if (cmnd_count == 0) + cmnd_count = 256; + } else if (cmd->cmnd[0] == WRITE_16) { + cmnd_lba = ((u64)cmd->cmnd[2] << 56) | + ((u64)cmd->cmnd[3] << 48) | + ((u64)cmd->cmnd[4] << 40) | + ((u64)cmd->cmnd[5] << 32) | + ((u64)cmd->cmnd[6] << 24) | + (cmd->cmnd[7] << 16) | + (cmd->cmnd[8] << 8) | + cmd->cmnd[9]; + cmnd_count = (cmd->cmnd[10] << 24) | + (cmd->cmnd[11] << 16) | + (cmd->cmnd[12] << 8) | + cmd->cmnd[13]; + } else if (cmd->cmnd[0] == WRITE_12) { + cmnd_lba = ((u64)cmd->cmnd[2] << 24) | + (cmd->cmnd[3] << 16) | + (cmd->cmnd[4] << 8) | + cmd->cmnd[5]; + cmnd_count = (cmd->cmnd[6] << 24) | + (cmd->cmnd[7] << 16) | + (cmd->cmnd[8] << 8) | + cmd->cmnd[9]; + } else if (cmd->cmnd[0] == WRITE_10) { + cmnd_lba = ((u64)cmd->cmnd[2] << 24) | + (cmd->cmnd[3] << 16) | + (cmd->cmnd[4] << 8) | + cmd->cmnd[5]; + cmnd_count = (cmd->cmnd[7] << 8) | + cmd->cmnd[8]; + } else + continue; + if (((cmnd_lba + cmnd_count) < lba) || + (count && ((lba + count) < cmnd_lba))) + continue; ++active; break; } @@ -1673,7 +1814,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd)); - synchronizecmd->count = + synchronizecmd->count = cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); /* @@ -1695,7 +1836,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) return 0; } - printk(KERN_WARNING + printk(KERN_WARNING "aac_synchronize: aac_fib_send failed with status: %d.\n", status); aac_fib_complete(cmd_fibcontext); aac_fib_free(cmd_fibcontext); @@ -1798,6 +1939,49 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid)); memset(&inq_data, 0, sizeof (struct inquiry_data)); + if (scsicmd->cmnd[1] & 0x1 ) { + char *arr = (char *)&inq_data; + + /* EVPD bit set */ + arr[0] = (scmd_id(scsicmd) == host->this_id) ? + INQD_PDT_PROC : INQD_PDT_DA; + if (scsicmd->cmnd[2] == 0) { + /* supported vital product data pages */ + arr[3] = 2; + arr[4] = 0x0; + arr[5] = 0x80; + arr[1] = scsicmd->cmnd[2]; + aac_internal_transfer(scsicmd, &inq_data, 0, + sizeof(inq_data)); + scsicmd->result = DID_OK << 16 | + COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + } else if (scsicmd->cmnd[2] == 0x80) { + /* unit serial number page */ + arr[3] = setinqserial(dev, &arr[4], + scmd_id(scsicmd)); + arr[1] = scsicmd->cmnd[2]; + aac_internal_transfer(scsicmd, &inq_data, 0, + sizeof(inq_data)); + return aac_get_container_serial(scsicmd); + } else { + /* vpd page not implemented */ + scsicmd->result = DID_OK << 16 | + COMMAND_COMPLETE << 8 | + SAM_STAT_CHECK_CONDITION; + set_sense((u8 *) &dev->fsa_dev[cid].sense_data, + ILLEGAL_REQUEST, + SENCODE_INVALID_CDB_FIELD, + ASENCODE_NO_SENSE, 0, 7, 2, 0); + memcpy(scsicmd->sense_buffer, + &dev->fsa_dev[cid].sense_data, + (sizeof(dev->fsa_dev[cid].sense_data) > + sizeof(scsicmd->sense_buffer)) + ? sizeof(scsicmd->sense_buffer) + : sizeof(dev->fsa_dev[cid].sense_data)); + } + scsicmd->scsi_done(scsicmd); + return 0; + } inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ inq_data.inqd_len = 31; @@ -2070,7 +2254,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg) } else return -EINVAL; - qd.valid = fsa_dev_ptr[qd.cnum].valid; + qd.valid = fsa_dev_ptr[qd.cnum].valid != 0; qd.locked = fsa_dev_ptr[qd.cnum].locked; qd.deleted = fsa_dev_ptr[qd.cnum].deleted; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index f1d3b66af87..94727b9375e 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,7 +12,7 @@ *----------------------------------------------------------------------------*/ #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 2447 +# define AAC_DRIVER_BUILD 2449 # define AAC_DRIVER_BRANCH "-ms" #endif #define MAXIMUM_NUM_CONTAINERS 32 @@ -1567,6 +1567,20 @@ struct aac_get_name_resp { u8 data[16]; }; +#define CT_CID_TO_32BITS_UID 165 +struct aac_get_serial { + __le32 command; /* VM_ContainerConfig */ + __le32 type; /* CT_CID_TO_32BITS_UID */ + __le32 cid; +}; + +struct aac_get_serial_resp { + __le32 dummy0; + __le32 dummy1; + __le32 status; /* CT_OK */ + __le32 uid; +}; + /* * The following command is sent to shut down each container. */ @@ -1793,10 +1807,10 @@ struct aac_aifcmd { * accounting for the fact capacity could be a 64 bit value * */ -static inline u32 cap_to_cyls(sector_t capacity, u32 divisor) +static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor) { sector_div(capacity, divisor); - return (u32)capacity; + return capacity; } /* SCp.phase values */ diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index d510839c0bb..bb870906b4c 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -80,7 +80,11 @@ static int fib_map_alloc(struct aac_dev *dev) void aac_fib_map_free(struct aac_dev *dev) { - pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa); + pci_free_consistent(dev->pdev, + dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), + dev->hw_fib_va, dev->hw_fib_pa); + dev->hw_fib_va = NULL; + dev->hw_fib_pa = 0; } /** @@ -1087,8 +1091,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) * case. */ aac_fib_map_free(aac); - aac->hw_fib_va = NULL; - aac->hw_fib_pa = 0; pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); aac->comm_addr = NULL; aac->comm_phys = 0; @@ -1098,12 +1100,12 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) kfree(aac->fsa_dev); aac->fsa_dev = NULL; if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) { - if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) || - ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK)))) + if (((retval = pci_set_dma_mask(aac->pdev, DMA_31BIT_MASK))) || + ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_31BIT_MASK)))) goto out; } else { - if (((retval = pci_set_dma_mask(aac->pdev, 0x7FFFFFFFULL))) || - ((retval = pci_set_consistent_dma_mask(aac->pdev, 0x7FFFFFFFULL)))) + if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) || + ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK)))) goto out; } if ((retval = (*(aac_get_driver_ident(index)->init))(aac))) diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index d76e1a8cb93..a7f42a17b5c 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -636,6 +636,8 @@ static int aac_cfg_open(struct inode *inode, struct file *file) static int aac_cfg_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; return aac_do_ioctl(file->private_data, cmd, (void __user *)arg); } @@ -689,6 +691,8 @@ static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; return aac_compat_do_ioctl((struct aac_dev *)file->private_data, cmd, arg); } #endif @@ -822,7 +826,7 @@ static ssize_t aac_show_reset_adapter(struct class_device *class_dev, tmp = aac_adapter_check_health(dev); if ((tmp == 0) && dev->in_reset) tmp = -EBUSY; - len = snprintf(buf, PAGE_SIZE, "0x%x", tmp); + len = snprintf(buf, PAGE_SIZE, "0x%x\n", tmp); return len; } @@ -1106,7 +1110,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, __aac_shutdown(aac); out_unmap: aac_fib_map_free(aac); - pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); + if (aac->comm_addr) + pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, + aac->comm_phys); kfree(aac->queues); aac_adapter_ioremap(aac, 0); kfree(aac->fibs); @@ -1122,9 +1128,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, static void aac_shutdown(struct pci_dev *dev) { struct Scsi_Host *shost = pci_get_drvdata(dev); - struct aac_dev *aac = (struct aac_dev *)shost->hostdata; scsi_block_requests(shost); - __aac_shutdown(aac); + __aac_shutdown((struct aac_dev *)shost->hostdata); } static void __devexit aac_remove_one(struct pci_dev *pdev) diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c index a8ace567781..c55f7c862f0 100644 --- a/drivers/scsi/aacraid/nark.c +++ b/drivers/scsi/aacraid/nark.c @@ -1,11 +1,10 @@ /* * Adaptec AAC series RAID controller driver - * (c) Copyright 2001 Red Hat Inc. <alan@redhat.com> * * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2006-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 9c5fcfb398c..8cd6588a83e 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index ebc65b9fea9..73eef3dc5dc 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -472,7 +472,7 @@ static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) else { bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); - if (!bled && (var != 0x00000001)) + if (!bled && (var != 0x00000001) && (var != 0x3803000F)) bled = -EINVAL; } if (bled && (bled != -ETIMEDOUT)) diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 2b6689709e5..79c0b6e37a3 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -1,4 +1,4 @@ -#define ASC_VERSION "3.3K" /* AdvanSys Driver Version */ +#define ASC_VERSION "3.3K" /* AdvanSys Driver Version */ /* * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters @@ -802,7 +802,6 @@ #include <linux/pci.h> #endif /* CONFIG_PCI */ - /* * --- Driver Options */ @@ -816,18 +815,6 @@ /* Enable driver tracing. */ /* #define ADVANSYS_DEBUG */ - -/* - * --- Debugging Header - */ - -#ifdef ADVANSYS_DEBUG -#define STATIC -#else /* ADVANSYS_DEBUG */ -#define STATIC static -#endif /* ADVANSYS_DEBUG */ - - /* * --- Asc Library Constants and Macros */ @@ -845,10 +832,10 @@ * are all consistent at 8, 16, and 32 bits respectively. Pointers * and long types are 64 bits on Alpha and UltraSPARC. */ -#define ASC_PADDR __u32 /* Physical/Bus address data type. */ -#define ASC_VADDR __u32 /* Virtual address data type. */ -#define ASC_DCNT __u32 /* Unsigned Data count type. */ -#define ASC_SDCNT __s32 /* Signed Data count type. */ +#define ASC_PADDR __u32 /* Physical/Bus address data type. */ +#define ASC_VADDR __u32 /* Virtual address data type. */ +#define ASC_DCNT __u32 /* Unsigned Data count type. */ +#define ASC_SDCNT __s32 /* Signed Data count type. */ /* * These macros are used to convert a virtual address to a @@ -911,7 +898,7 @@ typedef unsigned char uchar; #define CC_VERY_LONG_SG_LIST 0 #define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr) -#define PortAddr unsigned short /* port address size */ +#define PortAddr unsigned short /* port address size */ #define inp(port) inb(port) #define outp(port, byte) outb((byte), (port)) @@ -1038,17 +1025,17 @@ typedef unsigned char uchar; #define ASC_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2) typedef struct { - uchar periph; - uchar devtype; - uchar ver; - uchar byte3; - uchar add_len; - uchar res1; - uchar res2; - uchar flags; - uchar vendor_id[8]; - uchar product_id[16]; - uchar product_rev_level[4]; + uchar periph; + uchar devtype; + uchar ver; + uchar byte3; + uchar add_len; + uchar res1; + uchar res2; + uchar flags; + uchar vendor_id[8]; + uchar product_id[16]; + uchar product_rev_level[4]; } ASC_SCSI_INQUIRY; #define ASC_SG_LIST_PER_Q 7 @@ -1165,139 +1152,139 @@ typedef struct { #define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6)) typedef struct asc_scsiq_1 { - uchar status; - uchar q_no; - uchar cntl; - uchar sg_queue_cnt; - uchar target_id; - uchar target_lun; - ASC_PADDR data_addr; - ASC_DCNT data_cnt; - ASC_PADDR sense_addr; - uchar sense_len; - uchar extra_bytes; + uchar status; + uchar q_no; + uchar cntl; + uchar sg_queue_cnt; + uchar target_id; + uchar target_lun; + ASC_PADDR data_addr; + ASC_DCNT data_cnt; + ASC_PADDR sense_addr; + uchar sense_len; + uchar extra_bytes; } ASC_SCSIQ_1; typedef struct asc_scsiq_2 { - ASC_VADDR srb_ptr; - uchar target_ix; - uchar flag; - uchar cdb_len; - uchar tag_code; - ushort vm_id; + ASC_VADDR srb_ptr; + uchar target_ix; + uchar flag; + uchar cdb_len; + uchar tag_code; + ushort vm_id; } ASC_SCSIQ_2; typedef struct asc_scsiq_3 { - uchar done_stat; - uchar host_stat; - uchar scsi_stat; - uchar scsi_msg; + uchar done_stat; + uchar host_stat; + uchar scsi_stat; + uchar scsi_msg; } ASC_SCSIQ_3; typedef struct asc_scsiq_4 { - uchar cdb[ASC_MAX_CDB_LEN]; - uchar y_first_sg_list_qp; - uchar y_working_sg_qp; - uchar y_working_sg_ix; - uchar y_res; - ushort x_req_count; - ushort x_reconnect_rtn; - ASC_PADDR x_saved_data_addr; - ASC_DCNT x_saved_data_cnt; + uchar cdb[ASC_MAX_CDB_LEN]; + uchar y_first_sg_list_qp; + uchar y_working_sg_qp; + uchar y_working_sg_ix; + uchar y_res; + ushort x_req_count; + ushort x_reconnect_rtn; + ASC_PADDR x_saved_data_addr; + ASC_DCNT x_saved_data_cnt; } ASC_SCSIQ_4; typedef struct asc_q_done_info { - ASC_SCSIQ_2 d2; - ASC_SCSIQ_3 d3; - uchar q_status; - uchar q_no; - uchar cntl; - uchar sense_len; - uchar extra_bytes; - uchar res; - ASC_DCNT remain_bytes; + ASC_SCSIQ_2 d2; + ASC_SCSIQ_3 d3; + uchar q_status; + uchar q_no; + uchar cntl; + uchar sense_len; + uchar extra_bytes; + uchar res; + ASC_DCNT remain_bytes; } ASC_QDONE_INFO; typedef struct asc_sg_list { - ASC_PADDR addr; - ASC_DCNT bytes; + ASC_PADDR addr; + ASC_DCNT bytes; } ASC_SG_LIST; typedef struct asc_sg_head { - ushort entry_cnt; - ushort queue_cnt; - ushort entry_to_copy; - ushort res; - ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; + ushort entry_cnt; + ushort queue_cnt; + ushort entry_to_copy; + ushort res; + ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; } ASC_SG_HEAD; #define ASC_MIN_SG_LIST 2 typedef struct asc_min_sg_head { - ushort entry_cnt; - ushort queue_cnt; - ushort entry_to_copy; - ushort res; - ASC_SG_LIST sg_list[ASC_MIN_SG_LIST]; + ushort entry_cnt; + ushort queue_cnt; + ushort entry_to_copy; + ushort res; + ASC_SG_LIST sg_list[ASC_MIN_SG_LIST]; } ASC_MIN_SG_HEAD; #define QCX_SORT (0x0001) #define QCX_COALEASE (0x0002) typedef struct asc_scsi_q { - ASC_SCSIQ_1 q1; - ASC_SCSIQ_2 q2; - uchar *cdbptr; - ASC_SG_HEAD *sg_head; - ushort remain_sg_entry_cnt; - ushort next_sg_index; + ASC_SCSIQ_1 q1; + ASC_SCSIQ_2 q2; + uchar *cdbptr; + ASC_SG_HEAD *sg_head; + ushort remain_sg_entry_cnt; + ushort next_sg_index; } ASC_SCSI_Q; typedef struct asc_scsi_req_q { - ASC_SCSIQ_1 r1; - ASC_SCSIQ_2 r2; - uchar *cdbptr; - ASC_SG_HEAD *sg_head; - uchar *sense_ptr; - ASC_SCSIQ_3 r3; - uchar cdb[ASC_MAX_CDB_LEN]; - uchar sense[ASC_MIN_SENSE_LEN]; + ASC_SCSIQ_1 r1; + ASC_SCSIQ_2 r2; + uchar *cdbptr; + ASC_SG_HEAD *sg_head; + uchar *sense_ptr; + ASC_SCSIQ_3 r3; + uchar cdb[ASC_MAX_CDB_LEN]; + uchar sense[ASC_MIN_SENSE_LEN]; } ASC_SCSI_REQ_Q; typedef struct asc_scsi_bios_req_q { - ASC_SCSIQ_1 r1; - ASC_SCSIQ_2 r2; - uchar *cdbptr; - ASC_SG_HEAD *sg_head; - uchar *sense_ptr; - ASC_SCSIQ_3 r3; - uchar cdb[ASC_MAX_CDB_LEN]; - uchar sense[ASC_MIN_SENSE_LEN]; + ASC_SCSIQ_1 r1; + ASC_SCSIQ_2 r2; + uchar *cdbptr; + ASC_SG_HEAD *sg_head; + uchar *sense_ptr; + ASC_SCSIQ_3 r3; + uchar cdb[ASC_MAX_CDB_LEN]; + uchar sense[ASC_MIN_SENSE_LEN]; } ASC_SCSI_BIOS_REQ_Q; typedef struct asc_risc_q { - uchar fwd; - uchar bwd; - ASC_SCSIQ_1 i1; - ASC_SCSIQ_2 i2; - ASC_SCSIQ_3 i3; - ASC_SCSIQ_4 i4; + uchar fwd; + uchar bwd; + ASC_SCSIQ_1 i1; + ASC_SCSIQ_2 i2; + ASC_SCSIQ_3 i3; + ASC_SCSIQ_4 i4; } ASC_RISC_Q; typedef struct asc_sg_list_q { - uchar seq_no; - uchar q_no; - uchar cntl; - uchar sg_head_qp; - uchar sg_list_cnt; - uchar sg_cur_list_cnt; + uchar seq_no; + uchar q_no; + uchar cntl; + uchar sg_head_qp; + uchar sg_list_cnt; + uchar sg_cur_list_cnt; } ASC_SG_LIST_Q; typedef struct asc_risc_sg_list_q { - uchar fwd; - uchar bwd; - ASC_SG_LIST_Q sg; - ASC_SG_LIST sg_list[7]; + uchar fwd; + uchar bwd; + ASC_SG_LIST_Q sg; + ASC_SG_LIST sg_list[7]; } ASC_RISC_SG_LIST_Q; #define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL @@ -1431,25 +1418,25 @@ typedef struct asc_risc_sg_list_q { #define SYN_ULTRA_XFER_NS_15 107 typedef struct ext_msg { - uchar msg_type; - uchar msg_len; - uchar msg_req; - union { - struct { - uchar sdtr_xfer_period; - uchar sdtr_req_ack_offset; - } sdtr; - struct { - uchar wdtr_width; - } wdtr; - struct { - uchar mdp_b3; - uchar mdp_b2; - uchar mdp_b1; - uchar mdp_b0; - } mdp; - } u_ext_msg; - uchar res; + uchar msg_type; + uchar msg_len; + uchar msg_req; + union { + struct { + uchar sdtr_xfer_period; + uchar sdtr_req_ack_offset; + } sdtr; + struct { + uchar wdtr_width; + } wdtr; + struct { + uchar mdp_b3; + uchar mdp_b2; + uchar mdp_b1; + uchar mdp_b0; + } mdp; + } u_ext_msg; + uchar res; } EXT_MSG; #define xfer_period u_ext_msg.sdtr.sdtr_xfer_period @@ -1461,24 +1448,24 @@ typedef struct ext_msg { #define mdp_b0 u_ext_msg.mdp_b0 typedef struct asc_dvc_cfg { - ASC_SCSI_BIT_ID_TYPE can_tagged_qng; - ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled; - ASC_SCSI_BIT_ID_TYPE disc_enable; - ASC_SCSI_BIT_ID_TYPE sdtr_enable; - uchar chip_scsi_id; - uchar isa_dma_speed; - uchar isa_dma_channel; - uchar chip_version; - ushort lib_serial_no; - ushort lib_version; - ushort mcode_date; - ushort mcode_version; - uchar max_tag_qng[ASC_MAX_TID + 1]; - uchar *overrun_buf; - uchar sdtr_period_offset[ASC_MAX_TID + 1]; - ushort pci_slot_info; - uchar adapter_info[6]; - struct device *dev; + ASC_SCSI_BIT_ID_TYPE can_tagged_qng; + ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled; + ASC_SCSI_BIT_ID_TYPE disc_enable; + ASC_SCSI_BIT_ID_TYPE sdtr_enable; + uchar chip_scsi_id; + uchar isa_dma_speed; + uchar isa_dma_channel; + uchar chip_version; + ushort lib_serial_no; + ushort lib_version; + ushort mcode_date; + ushort mcode_version; + uchar max_tag_qng[ASC_MAX_TID + 1]; + uchar *overrun_buf; + uchar sdtr_period_offset[ASC_MAX_TID + 1]; + ushort pci_slot_info; + uchar adapter_info[6]; + struct device *dev; } ASC_DVC_CFG; #define ASC_DEF_DVC_CNTL 0xFFFF @@ -1501,64 +1488,64 @@ typedef struct asc_dvc_cfg { #define ASC_MIN_TAGGED_CMD 7 #define ASC_MAX_SCSI_RESET_WAIT 30 -struct asc_dvc_var; /* Forward Declaration. */ +struct asc_dvc_var; /* Forward Declaration. */ -typedef void (* ASC_ISR_CALLBACK)(struct asc_dvc_var *, ASC_QDONE_INFO *); -typedef int (* ASC_EXE_CALLBACK)(struct asc_dvc_var *, ASC_SCSI_Q *); +typedef void (*ASC_ISR_CALLBACK) (struct asc_dvc_var *, ASC_QDONE_INFO *); +typedef int (*ASC_EXE_CALLBACK) (struct asc_dvc_var *, ASC_SCSI_Q *); typedef struct asc_dvc_var { - PortAddr iop_base; - ushort err_code; - ushort dvc_cntl; - ushort bug_fix_cntl; - ushort bus_type; - ASC_ISR_CALLBACK isr_callback; - ASC_EXE_CALLBACK exe_callback; - ASC_SCSI_BIT_ID_TYPE init_sdtr; - ASC_SCSI_BIT_ID_TYPE sdtr_done; - ASC_SCSI_BIT_ID_TYPE use_tagged_qng; - ASC_SCSI_BIT_ID_TYPE unit_not_ready; - ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; - ASC_SCSI_BIT_ID_TYPE start_motor; - uchar scsi_reset_wait; - uchar chip_no; - char is_in_int; - uchar max_total_qng; - uchar cur_total_qng; - uchar in_critical_cnt; - uchar irq_no; - uchar last_q_shortage; - ushort init_state; - uchar cur_dvc_qng[ASC_MAX_TID + 1]; - uchar max_dvc_qng[ASC_MAX_TID + 1]; - ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1]; - ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1]; - uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO]; - ASC_DVC_CFG *cfg; - ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always; - char redo_scam; - ushort res2; - uchar dos_int13_table[ASC_MAX_TID + 1]; - ASC_DCNT max_dma_count; - ASC_SCSI_BIT_ID_TYPE no_scam; - ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer; - uchar max_sdtr_index; - uchar host_init_sdtr_index; - struct asc_board *drv_ptr; - ASC_DCNT uc_break; + PortAddr iop_base; + ushort err_code; + ushort dvc_cntl; + ushort bug_fix_cntl; + ushort bus_type; + ASC_ISR_CALLBACK isr_callback; + ASC_EXE_CALLBACK exe_callback; + ASC_SCSI_BIT_ID_TYPE init_sdtr; + ASC_SCSI_BIT_ID_TYPE sdtr_done; + ASC_SCSI_BIT_ID_TYPE use_tagged_qng; + ASC_SCSI_BIT_ID_TYPE unit_not_ready; + ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; + ASC_SCSI_BIT_ID_TYPE start_motor; + uchar scsi_reset_wait; + uchar chip_no; + char is_in_int; + uchar max_total_qng; + uchar cur_total_qng; + uchar in_critical_cnt; + uchar irq_no; + uchar last_q_shortage; + ushort init_state; + uchar cur_dvc_qng[ASC_MAX_TID + 1]; + uchar max_dvc_qng[ASC_MAX_TID + 1]; + ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1]; + ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1]; + uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO]; + ASC_DVC_CFG *cfg; + ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always; + char redo_scam; + ushort res2; + uchar dos_int13_table[ASC_MAX_TID + 1]; + ASC_DCNT max_dma_count; + ASC_SCSI_BIT_ID_TYPE no_scam; + ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer; + uchar max_sdtr_index; + uchar host_init_sdtr_index; + struct asc_board *drv_ptr; + ASC_DCNT uc_break; } ASC_DVC_VAR; typedef struct asc_dvc_inq_info { - uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; + uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; } ASC_DVC_INQ_INFO; typedef struct asc_cap_info { - ASC_DCNT lba; - ASC_DCNT blk_size; + ASC_DCNT lba; + ASC_DCNT blk_size; } ASC_CAP_INFO; typedef struct asc_cap_info_array { - ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; + ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; } ASC_CAP_INFO_ARRAY; #define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001 @@ -1603,23 +1590,23 @@ typedef struct asc_cap_info_array { ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4) typedef struct asceep_config { - ushort cfg_lsw; - ushort cfg_msw; - uchar init_sdtr; - uchar disc_enable; - uchar use_cmd_qng; - uchar start_motor; - uchar max_total_qng; - uchar max_tag_qng; - uchar bios_scan; - uchar power_up_wait; - uchar no_scam; - uchar id_speed; /* low order 4 bits is chip scsi id */ - /* high order 4 bits is isa dma speed */ - uchar dos_int13_table[ASC_MAX_TID + 1]; - uchar adapter_info[6]; - ushort cntl; - ushort chksum; + ushort cfg_lsw; + ushort cfg_msw; + uchar init_sdtr; + uchar disc_enable; + uchar use_cmd_qng; + uchar start_motor; + uchar max_total_qng; + uchar max_tag_qng; + uchar bios_scan; + uchar power_up_wait; + uchar no_scam; + uchar id_speed; /* low order 4 bits is chip scsi id */ + /* high order 4 bits is isa dma speed */ + uchar dos_int13_table[ASC_MAX_TID + 1]; + uchar adapter_info[6]; + ushort cntl; + ushort chksum; } ASCEEP_CONFIG; #define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800 @@ -1827,8 +1814,8 @@ typedef struct asceep_config { #define ASC_MC_SAVE_DATA_WSIZE 0x40 typedef struct asc_mc_saved { - ushort data[ASC_MC_SAVE_DATA_WSIZE]; - ushort code[ASC_MC_SAVE_CODE_WSIZE]; + ushort data[ASC_MC_SAVE_DATA_WSIZE]; + ushort code[ASC_MC_SAVE_CODE_WSIZE]; } ASC_MC_SAVED; #define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B) @@ -1900,120 +1887,113 @@ typedef struct asc_mc_saved { #define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID) #define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data) -STATIC int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg); -STATIC int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg); -STATIC void AscWaitEEPRead(void); -STATIC void AscWaitEEPWrite(void); -STATIC ushort AscReadEEPWord(PortAddr, uchar); -STATIC ushort AscWriteEEPWord(PortAddr, uchar, ushort); -STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); -STATIC int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort); -STATIC int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); -STATIC int AscStartChip(PortAddr); -STATIC int AscStopChip(PortAddr); -STATIC void AscSetChipIH(PortAddr, ushort); -STATIC int AscIsChipHalted(PortAddr); -STATIC void AscAckInterrupt(PortAddr); -STATIC void AscDisableInterrupt(PortAddr); -STATIC void AscEnableInterrupt(PortAddr); -STATIC void AscSetBank(PortAddr, uchar); -STATIC int AscResetChipAndScsiBus(ASC_DVC_VAR *); +static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg); +static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg); +static void AscWaitEEPRead(void); +static void AscWaitEEPWrite(void); +static ushort AscReadEEPWord(PortAddr, uchar); +static ushort AscWriteEEPWord(PortAddr, uchar, ushort); +static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); +static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort); +static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); +static int AscStartChip(PortAddr); +static int AscStopChip(PortAddr); +static void AscSetChipIH(PortAddr, ushort); +static int AscIsChipHalted(PortAddr); +static void AscAckInterrupt(PortAddr); +static void AscDisableInterrupt(PortAddr); +static void AscEnableInterrupt(PortAddr); +static void AscSetBank(PortAddr, uchar); +static int AscResetChipAndScsiBus(ASC_DVC_VAR *); #ifdef CONFIG_ISA -STATIC ushort AscGetIsaDmaChannel(PortAddr); -STATIC ushort AscSetIsaDmaChannel(PortAddr, ushort); -STATIC uchar AscSetIsaDmaSpeed(PortAddr, uchar); -STATIC uchar AscGetIsaDmaSpeed(PortAddr); +static ushort AscGetIsaDmaChannel(PortAddr); +static ushort AscSetIsaDmaChannel(PortAddr, ushort); +static uchar AscSetIsaDmaSpeed(PortAddr, uchar); +static uchar AscGetIsaDmaSpeed(PortAddr); #endif /* CONFIG_ISA */ -STATIC uchar AscReadLramByte(PortAddr, ushort); -STATIC ushort AscReadLramWord(PortAddr, ushort); +static uchar AscReadLramByte(PortAddr, ushort); +static ushort AscReadLramWord(PortAddr, ushort); #if CC_VERY_LONG_SG_LIST -STATIC ASC_DCNT AscReadLramDWord(PortAddr, ushort); +static ASC_DCNT AscReadLramDWord(PortAddr, ushort); #endif /* CC_VERY_LONG_SG_LIST */ -STATIC void AscWriteLramWord(PortAddr, ushort, ushort); -STATIC void AscWriteLramByte(PortAddr, ushort, uchar); -STATIC ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int); -STATIC void AscMemWordSetLram(PortAddr, ushort, ushort, int); -STATIC void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int); -STATIC void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int); -STATIC void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int); -STATIC ushort AscInitAscDvcVar(ASC_DVC_VAR *); -STATIC ushort AscInitFromEEP(ASC_DVC_VAR *); -STATIC ushort AscInitFromAscDvcVar(ASC_DVC_VAR *); -STATIC ushort AscInitMicroCodeVar(ASC_DVC_VAR *); -STATIC int AscTestExternalLram(ASC_DVC_VAR *); -STATIC uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar); -STATIC uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar); -STATIC void AscSetChipSDTR(PortAddr, uchar, uchar); -STATIC uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar); -STATIC uchar AscAllocFreeQueue(PortAddr, uchar); -STATIC uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar); -STATIC int AscHostReqRiscHalt(PortAddr); -STATIC int AscStopQueueExe(PortAddr); -STATIC int AscSendScsiQueue(ASC_DVC_VAR *, - ASC_SCSI_Q * scsiq, - uchar n_q_required); -STATIC int AscPutReadyQueue(ASC_DVC_VAR *, - ASC_SCSI_Q *, uchar); -STATIC int AscPutReadySgListQueue(ASC_DVC_VAR *, - ASC_SCSI_Q *, uchar); -STATIC int AscSetChipSynRegAtID(PortAddr, uchar, uchar); -STATIC int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); -STATIC ushort AscInitLram(ASC_DVC_VAR *); -STATIC ushort AscInitQLinkVar(ASC_DVC_VAR *); -STATIC int AscSetLibErrorCode(ASC_DVC_VAR *, ushort); -STATIC int AscIsrChipHalted(ASC_DVC_VAR *); -STATIC uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, - ASC_QDONE_INFO *, ASC_DCNT); -STATIC int AscIsrQDone(ASC_DVC_VAR *); -STATIC int AscCompareString(uchar *, uchar *, int); +static void AscWriteLramWord(PortAddr, ushort, ushort); +static void AscWriteLramByte(PortAddr, ushort, uchar); +static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int); +static void AscMemWordSetLram(PortAddr, ushort, ushort, int); +static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int); +static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int); +static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int); +static ushort AscInitAscDvcVar(ASC_DVC_VAR *); +static ushort AscInitFromEEP(ASC_DVC_VAR *); +static ushort AscInitFromAscDvcVar(ASC_DVC_VAR *); +static ushort AscInitMicroCodeVar(ASC_DVC_VAR *); +static int AscTestExternalLram(ASC_DVC_VAR *); +static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar); +static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar); +static void AscSetChipSDTR(PortAddr, uchar, uchar); +static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar); +static uchar AscAllocFreeQueue(PortAddr, uchar); +static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar); +static int AscHostReqRiscHalt(PortAddr); +static int AscStopQueueExe(PortAddr); +static int AscSendScsiQueue(ASC_DVC_VAR *, + ASC_SCSI_Q *scsiq, uchar n_q_required); +static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar); +static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar); +static int AscSetChipSynRegAtID(PortAddr, uchar, uchar); +static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); +static ushort AscInitLram(ASC_DVC_VAR *); +static ushort AscInitQLinkVar(ASC_DVC_VAR *); +static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort); +static int AscIsrChipHalted(ASC_DVC_VAR *); +static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, + ASC_QDONE_INFO *, ASC_DCNT); +static int AscIsrQDone(ASC_DVC_VAR *); +static int AscCompareString(uchar *, uchar *, int); #ifdef CONFIG_ISA -STATIC ushort AscGetEisaChipCfg(PortAddr); -STATIC ASC_DCNT AscGetEisaProductID(PortAddr); -STATIC PortAddr AscSearchIOPortAddrEISA(PortAddr); -STATIC PortAddr AscSearchIOPortAddr11(PortAddr); -STATIC PortAddr AscSearchIOPortAddr(PortAddr, ushort); -STATIC void AscSetISAPNPWaitForKey(void); +static ushort AscGetEisaChipCfg(PortAddr); +static ASC_DCNT AscGetEisaProductID(PortAddr); +static PortAddr AscSearchIOPortAddrEISA(PortAddr); +static PortAddr AscSearchIOPortAddr11(PortAddr); +static PortAddr AscSearchIOPortAddr(PortAddr, ushort); +static void AscSetISAPNPWaitForKey(void); #endif /* CONFIG_ISA */ -STATIC uchar AscGetChipScsiCtrl(PortAddr); -STATIC uchar AscSetChipScsiID(PortAddr, uchar); -STATIC uchar AscGetChipVersion(PortAddr, ushort); -STATIC ushort AscGetChipBusType(PortAddr); -STATIC ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort); -STATIC int AscFindSignature(PortAddr); -STATIC void AscToggleIRQAct(PortAddr); -STATIC uchar AscGetChipIRQ(PortAddr, ushort); -STATIC uchar AscSetChipIRQ(PortAddr, uchar, ushort); -STATIC ushort AscGetChipBiosAddress(PortAddr, ushort); -STATIC inline ulong DvcEnterCritical(void); -STATIC inline void DvcLeaveCritical(ulong); +static uchar AscGetChipScsiCtrl(PortAddr); +static uchar AscSetChipScsiID(PortAddr, uchar); +static uchar AscGetChipVersion(PortAddr, ushort); +static ushort AscGetChipBusType(PortAddr); +static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort); +static int AscFindSignature(PortAddr); +static void AscToggleIRQAct(PortAddr); +static uchar AscGetChipIRQ(PortAddr, ushort); +static uchar AscSetChipIRQ(PortAddr, uchar, ushort); +static ushort AscGetChipBiosAddress(PortAddr, ushort); +static inline ulong DvcEnterCritical(void); +static inline void DvcLeaveCritical(ulong); #ifdef CONFIG_PCI -STATIC uchar DvcReadPCIConfigByte(ASC_DVC_VAR *, ushort); -STATIC void DvcWritePCIConfigByte(ASC_DVC_VAR *, - ushort, uchar); +static uchar DvcReadPCIConfigByte(ASC_DVC_VAR *, ushort); +static void DvcWritePCIConfigByte(ASC_DVC_VAR *, ushort, uchar); #endif /* CONFIG_PCI */ -STATIC ushort AscGetChipBiosAddress(PortAddr, ushort); -STATIC void DvcSleepMilliSecond(ASC_DCNT); -STATIC void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT); -STATIC void DvcPutScsiQ(PortAddr, ushort, uchar *, int); -STATIC void DvcGetQinfo(PortAddr, ushort, uchar *, int); -STATIC ushort AscInitGetConfig(ASC_DVC_VAR *); -STATIC ushort AscInitSetConfig(ASC_DVC_VAR *); -STATIC ushort AscInitAsc1000Driver(ASC_DVC_VAR *); -STATIC void AscAsyncFix(ASC_DVC_VAR *, uchar, - ASC_SCSI_INQUIRY *); -STATIC int AscTagQueuingSafe(ASC_SCSI_INQUIRY *); -STATIC void AscInquiryHandling(ASC_DVC_VAR *, - uchar, ASC_SCSI_INQUIRY *); -STATIC int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *); -STATIC int AscISR(ASC_DVC_VAR *); -STATIC uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, - uchar); -STATIC int AscSgListToQueue(int); +static ushort AscGetChipBiosAddress(PortAddr, ushort); +static void DvcSleepMilliSecond(ASC_DCNT); +static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT); +static void DvcPutScsiQ(PortAddr, ushort, uchar *, int); +static void DvcGetQinfo(PortAddr, ushort, uchar *, int); +static ushort AscInitGetConfig(ASC_DVC_VAR *); +static ushort AscInitSetConfig(ASC_DVC_VAR *); +static ushort AscInitAsc1000Driver(ASC_DVC_VAR *); +static void AscAsyncFix(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *); +static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *); +static void AscInquiryHandling(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *); +static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *); +static int AscISR(ASC_DVC_VAR *); +static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar); +static int AscSgListToQueue(int); #ifdef CONFIG_ISA -STATIC void AscEnableIsaDma(uchar); +static void AscEnableIsaDma(uchar); #endif /* CONFIG_ISA */ -STATIC ASC_DCNT AscGetMaxDmaCount(ushort); -static const char *advansys_info(struct Scsi_Host *shp); +static ASC_DCNT AscGetMaxDmaCount(ushort); +static const char *advansys_info(struct Scsi_Host *shost); /* * --- Adv Library Constants and Macros @@ -2035,10 +2015,10 @@ static const char *advansys_info(struct Scsi_Host *shp); * are all consistent at 8, 16, and 32 bits respectively. Pointers * and long types are 64 bits on Alpha and UltraSPARC. */ -#define ADV_PADDR __u32 /* Physical address data type. */ -#define ADV_VADDR __u32 /* Virtual address data type. */ -#define ADV_DCNT __u32 /* Unsigned Data count type. */ -#define ADV_SDCNT __s32 /* Signed Data count type. */ +#define ADV_PADDR __u32 /* Physical address data type. */ +#define ADV_VADDR __u32 /* Virtual address data type. */ +#define ADV_DCNT __u32 /* Unsigned Data count type. */ +#define ADV_SDCNT __s32 /* Signed Data count type. */ /* * These macros are used to convert a virtual address to a @@ -2051,7 +2031,7 @@ static const char *advansys_info(struct Scsi_Host *shp); #define ADV_VADDR_TO_U32 virt_to_bus #define ADV_U32_TO_VADDR bus_to_virt -#define AdvPortAddr void __iomem * /* Virtual memory address size */ +#define AdvPortAddr void __iomem * /* Virtual memory address size */ /* * Define Adv Library required memory access macros. @@ -2103,20 +2083,20 @@ static const char *advansys_info(struct Scsi_Host *shp); #define ADV_EEP_DVC_CFG_BEGIN (0x00) #define ADV_EEP_DVC_CFG_END (0x15) -#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */ +#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */ #define ADV_EEP_MAX_WORD_ADDR (0x1E) #define ADV_EEP_DELAY_MS 100 -#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */ -#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */ +#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */ +#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */ /* * For the ASC3550 Bit 13 is Termination Polarity control bit. * For later ICs Bit 13 controls whether the CIS (Card Information * Service Section) is loaded from EEPROM. */ -#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */ -#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */ +#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */ +#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */ /* * ASC38C1600 Bit 11 * @@ -2128,280 +2108,277 @@ static const char *advansys_info(struct Scsi_Host *shp); * INT B in the PCI Configuration Space Int Pin field. If it is 1, then * Function 1 will specify INT A. */ -#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */ - -typedef struct adveep_3550_config -{ - /* Word Offset, Description */ - - ushort cfg_lsw; /* 00 power up initialization */ - /* bit 13 set - Term Polarity Control */ - /* bit 14 set - BIOS Enable */ - /* bit 15 set - Big Endian Mode */ - ushort cfg_msw; /* 01 unused */ - ushort disc_enable; /* 02 disconnect enable */ - ushort wdtr_able; /* 03 Wide DTR able */ - ushort sdtr_able; /* 04 Synchronous DTR able */ - ushort start_motor; /* 05 send start up motor */ - ushort tagqng_able; /* 06 tag queuing able */ - ushort bios_scan; /* 07 BIOS device control */ - ushort scam_tolerant; /* 08 no scam */ - - uchar adapter_scsi_id; /* 09 Host Adapter ID */ - uchar bios_boot_delay; /* power up wait */ - - uchar scsi_reset_delay; /* 10 reset delay */ - uchar bios_id_lun; /* first boot device scsi id & lun */ - /* high nibble is lun */ - /* low nibble is scsi id */ - - uchar termination; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - uchar reserved1; /* reserved byte (not used) */ - - ushort bios_ctrl; /* 12 BIOS control bits */ - /* bit 0 BIOS don't act as initiator. */ - /* bit 1 BIOS > 1 GB support */ - /* bit 2 BIOS > 2 Disk Support */ - /* bit 3 BIOS don't support removables */ - /* bit 4 BIOS support bootable CD */ - /* bit 5 BIOS scan enabled */ - /* bit 6 BIOS support multiple LUNs */ - /* bit 7 BIOS display of message */ - /* bit 8 SCAM disabled */ - /* bit 9 Reset SCSI bus during init. */ - /* bit 10 */ - /* bit 11 No verbose initialization. */ - /* bit 12 SCSI parity enabled */ - /* bit 13 */ - /* bit 14 */ - /* bit 15 */ - ushort ultra_able; /* 13 ULTRA speed able */ - ushort reserved2; /* 14 reserved */ - uchar max_host_qng; /* 15 maximum host queuing */ - uchar max_dvc_qng; /* maximum per device queuing */ - ushort dvc_cntl; /* 16 control bit for driver */ - ushort bug_fix; /* 17 control bit for bug fix */ - ushort serial_number_word1; /* 18 Board serial number word 1 */ - ushort serial_number_word2; /* 19 Board serial number word 2 */ - ushort serial_number_word3; /* 20 Board serial number word 3 */ - ushort check_sum; /* 21 EEP check sum */ - uchar oem_name[16]; /* 22 OEM name */ - ushort dvc_err_code; /* 30 last device driver error code */ - ushort adv_err_code; /* 31 last uc and Adv Lib error code */ - ushort adv_err_addr; /* 32 last uc error address */ - ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ - ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ - ushort saved_adv_err_addr; /* 35 saved last uc error address */ - ushort num_of_err; /* 36 number of error */ +#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */ + +typedef struct adveep_3550_config { + /* Word Offset, Description */ + + ushort cfg_lsw; /* 00 power up initialization */ + /* bit 13 set - Term Polarity Control */ + /* bit 14 set - BIOS Enable */ + /* bit 15 set - Big Endian Mode */ + ushort cfg_msw; /* 01 unused */ + ushort disc_enable; /* 02 disconnect enable */ + ushort wdtr_able; /* 03 Wide DTR able */ + ushort sdtr_able; /* 04 Synchronous DTR able */ + ushort start_motor; /* 05 send start up motor */ + ushort tagqng_able; /* 06 tag queuing able */ + ushort bios_scan; /* 07 BIOS device control */ + ushort scam_tolerant; /* 08 no scam */ + + uchar adapter_scsi_id; /* 09 Host Adapter ID */ + uchar bios_boot_delay; /* power up wait */ + + uchar scsi_reset_delay; /* 10 reset delay */ + uchar bios_id_lun; /* first boot device scsi id & lun */ + /* high nibble is lun */ + /* low nibble is scsi id */ + + uchar termination; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + uchar reserved1; /* reserved byte (not used) */ + + ushort bios_ctrl; /* 12 BIOS control bits */ + /* bit 0 BIOS don't act as initiator. */ + /* bit 1 BIOS > 1 GB support */ + /* bit 2 BIOS > 2 Disk Support */ + /* bit 3 BIOS don't support removables */ + /* bit 4 BIOS support bootable CD */ + /* bit 5 BIOS scan enabled */ + /* bit 6 BIOS support multiple LUNs */ + /* bit 7 BIOS display of message */ + /* bit 8 SCAM disabled */ + /* bit 9 Reset SCSI bus during init. */ + /* bit 10 */ + /* bit 11 No verbose initialization. */ + /* bit 12 SCSI parity enabled */ + /* bit 13 */ + /* bit 14 */ + /* bit 15 */ + ushort ultra_able; /* 13 ULTRA speed able */ + ushort reserved2; /* 14 reserved */ + uchar max_host_qng; /* 15 maximum host queuing */ + uchar max_dvc_qng; /* maximum per device queuing */ + ushort dvc_cntl; /* 16 control bit for driver */ + ushort bug_fix; /* 17 control bit for bug fix */ + ushort serial_number_word1; /* 18 Board serial number word 1 */ + ushort serial_number_word2; /* 19 Board serial number word 2 */ + ushort serial_number_word3; /* 20 Board serial number word 3 */ + ushort check_sum; /* 21 EEP check sum */ + uchar oem_name[16]; /* 22 OEM name */ + ushort dvc_err_code; /* 30 last device driver error code */ + ushort adv_err_code; /* 31 last uc and Adv Lib error code */ + ushort adv_err_addr; /* 32 last uc error address */ + ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ + ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ + ushort saved_adv_err_addr; /* 35 saved last uc error address */ + ushort num_of_err; /* 36 number of error */ } ADVEEP_3550_CONFIG; -typedef struct adveep_38C0800_config -{ - /* Word Offset, Description */ - - ushort cfg_lsw; /* 00 power up initialization */ - /* bit 13 set - Load CIS */ - /* bit 14 set - BIOS Enable */ - /* bit 15 set - Big Endian Mode */ - ushort cfg_msw; /* 01 unused */ - ushort disc_enable; /* 02 disconnect enable */ - ushort wdtr_able; /* 03 Wide DTR able */ - ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */ - ushort start_motor; /* 05 send start up motor */ - ushort tagqng_able; /* 06 tag queuing able */ - ushort bios_scan; /* 07 BIOS device control */ - ushort scam_tolerant; /* 08 no scam */ - - uchar adapter_scsi_id; /* 09 Host Adapter ID */ - uchar bios_boot_delay; /* power up wait */ - - uchar scsi_reset_delay; /* 10 reset delay */ - uchar bios_id_lun; /* first boot device scsi id & lun */ - /* high nibble is lun */ - /* low nibble is scsi id */ - - uchar termination_se; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - uchar termination_lvd; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - ushort bios_ctrl; /* 12 BIOS control bits */ - /* bit 0 BIOS don't act as initiator. */ - /* bit 1 BIOS > 1 GB support */ - /* bit 2 BIOS > 2 Disk Support */ - /* bit 3 BIOS don't support removables */ - /* bit 4 BIOS support bootable CD */ - /* bit 5 BIOS scan enabled */ - /* bit 6 BIOS support multiple LUNs */ - /* bit 7 BIOS display of message */ - /* bit 8 SCAM disabled */ - /* bit 9 Reset SCSI bus during init. */ - /* bit 10 */ - /* bit 11 No verbose initialization. */ - /* bit 12 SCSI parity enabled */ - /* bit 13 */ - /* bit 14 */ - /* bit 15 */ - ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */ - ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */ - uchar max_host_qng; /* 15 maximum host queueing */ - uchar max_dvc_qng; /* maximum per device queuing */ - ushort dvc_cntl; /* 16 control bit for driver */ - ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */ - ushort serial_number_word1; /* 18 Board serial number word 1 */ - ushort serial_number_word2; /* 19 Board serial number word 2 */ - ushort serial_number_word3; /* 20 Board serial number word 3 */ - ushort check_sum; /* 21 EEP check sum */ - uchar oem_name[16]; /* 22 OEM name */ - ushort dvc_err_code; /* 30 last device driver error code */ - ushort adv_err_code; /* 31 last uc and Adv Lib error code */ - ushort adv_err_addr; /* 32 last uc error address */ - ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ - ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ - ushort saved_adv_err_addr; /* 35 saved last uc error address */ - ushort reserved36; /* 36 reserved */ - ushort reserved37; /* 37 reserved */ - ushort reserved38; /* 38 reserved */ - ushort reserved39; /* 39 reserved */ - ushort reserved40; /* 40 reserved */ - ushort reserved41; /* 41 reserved */ - ushort reserved42; /* 42 reserved */ - ushort reserved43; /* 43 reserved */ - ushort reserved44; /* 44 reserved */ - ushort reserved45; /* 45 reserved */ - ushort reserved46; /* 46 reserved */ - ushort reserved47; /* 47 reserved */ - ushort reserved48; /* 48 reserved */ - ushort reserved49; /* 49 reserved */ - ushort reserved50; /* 50 reserved */ - ushort reserved51; /* 51 reserved */ - ushort reserved52; /* 52 reserved */ - ushort reserved53; /* 53 reserved */ - ushort reserved54; /* 54 reserved */ - ushort reserved55; /* 55 reserved */ - ushort cisptr_lsw; /* 56 CIS PTR LSW */ - ushort cisprt_msw; /* 57 CIS PTR MSW */ - ushort subsysvid; /* 58 SubSystem Vendor ID */ - ushort subsysid; /* 59 SubSystem ID */ - ushort reserved60; /* 60 reserved */ - ushort reserved61; /* 61 reserved */ - ushort reserved62; /* 62 reserved */ - ushort reserved63; /* 63 reserved */ +typedef struct adveep_38C0800_config { + /* Word Offset, Description */ + + ushort cfg_lsw; /* 00 power up initialization */ + /* bit 13 set - Load CIS */ + /* bit 14 set - BIOS Enable */ + /* bit 15 set - Big Endian Mode */ + ushort cfg_msw; /* 01 unused */ + ushort disc_enable; /* 02 disconnect enable */ + ushort wdtr_able; /* 03 Wide DTR able */ + ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */ + ushort start_motor; /* 05 send start up motor */ + ushort tagqng_able; /* 06 tag queuing able */ + ushort bios_scan; /* 07 BIOS device control */ + ushort scam_tolerant; /* 08 no scam */ + + uchar adapter_scsi_id; /* 09 Host Adapter ID */ + uchar bios_boot_delay; /* power up wait */ + + uchar scsi_reset_delay; /* 10 reset delay */ + uchar bios_id_lun; /* first boot device scsi id & lun */ + /* high nibble is lun */ + /* low nibble is scsi id */ + + uchar termination_se; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + uchar termination_lvd; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + ushort bios_ctrl; /* 12 BIOS control bits */ + /* bit 0 BIOS don't act as initiator. */ + /* bit 1 BIOS > 1 GB support */ + /* bit 2 BIOS > 2 Disk Support */ + /* bit 3 BIOS don't support removables */ + /* bit 4 BIOS support bootable CD */ + /* bit 5 BIOS scan enabled */ + /* bit 6 BIOS support multiple LUNs */ + /* bit 7 BIOS display of message */ + /* bit 8 SCAM disabled */ + /* bit 9 Reset SCSI bus during init. */ + /* bit 10 */ + /* bit 11 No verbose initialization. */ + /* bit 12 SCSI parity enabled */ + /* bit 13 */ + /* bit 14 */ + /* bit 15 */ + ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */ + ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */ + uchar max_host_qng; /* 15 maximum host queueing */ + uchar max_dvc_qng; /* maximum per device queuing */ + ushort dvc_cntl; /* 16 control bit for driver */ + ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */ + ushort serial_number_word1; /* 18 Board serial number word 1 */ + ushort serial_number_word2; /* 19 Board serial number word 2 */ + ushort serial_number_word3; /* 20 Board serial number word 3 */ + ushort check_sum; /* 21 EEP check sum */ + uchar oem_name[16]; /* 22 OEM name */ + ushort dvc_err_code; /* 30 last device driver error code */ + ushort adv_err_code; /* 31 last uc and Adv Lib error code */ + ushort adv_err_addr; /* 32 last uc error address */ + ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ + ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ + ushort saved_adv_err_addr; /* 35 saved last uc error address */ + ushort reserved36; /* 36 reserved */ + ushort reserved37; /* 37 reserved */ + ushort reserved38; /* 38 reserved */ + ushort reserved39; /* 39 reserved */ + ushort reserved40; /* 40 reserved */ + ushort reserved41; /* 41 reserved */ + ushort reserved42; /* 42 reserved */ + ushort reserved43; /* 43 reserved */ + ushort reserved44; /* 44 reserved */ + ushort reserved45; /* 45 reserved */ + ushort reserved46; /* 46 reserved */ + ushort reserved47; /* 47 reserved */ + ushort reserved48; /* 48 reserved */ + ushort reserved49; /* 49 reserved */ + ushort reserved50; /* 50 reserved */ + ushort reserved51; /* 51 reserved */ + ushort reserved52; /* 52 reserved */ + ushort reserved53; /* 53 reserved */ + ushort reserved54; /* 54 reserved */ + ushort reserved55; /* 55 reserved */ + ushort cisptr_lsw; /* 56 CIS PTR LSW */ + ushort cisprt_msw; /* 57 CIS PTR MSW */ + ushort subsysvid; /* 58 SubSystem Vendor ID */ + ushort subsysid; /* 59 SubSystem ID */ + ushort reserved60; /* 60 reserved */ + ushort reserved61; /* 61 reserved */ + ushort reserved62; /* 62 reserved */ + ushort reserved63; /* 63 reserved */ } ADVEEP_38C0800_CONFIG; -typedef struct adveep_38C1600_config -{ - /* Word Offset, Description */ - - ushort cfg_lsw; /* 00 power up initialization */ - /* bit 11 set - Func. 0 INTB, Func. 1 INTA */ - /* clear - Func. 0 INTA, Func. 1 INTB */ - /* bit 13 set - Load CIS */ - /* bit 14 set - BIOS Enable */ - /* bit 15 set - Big Endian Mode */ - ushort cfg_msw; /* 01 unused */ - ushort disc_enable; /* 02 disconnect enable */ - ushort wdtr_able; /* 03 Wide DTR able */ - ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */ - ushort start_motor; /* 05 send start up motor */ - ushort tagqng_able; /* 06 tag queuing able */ - ushort bios_scan; /* 07 BIOS device control */ - ushort scam_tolerant; /* 08 no scam */ - - uchar adapter_scsi_id; /* 09 Host Adapter ID */ - uchar bios_boot_delay; /* power up wait */ - - uchar scsi_reset_delay; /* 10 reset delay */ - uchar bios_id_lun; /* first boot device scsi id & lun */ - /* high nibble is lun */ - /* low nibble is scsi id */ - - uchar termination_se; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - uchar termination_lvd; /* 11 0 - automatic */ - /* 1 - low off / high off */ - /* 2 - low off / high on */ - /* 3 - low on / high on */ - /* There is no low on / high off */ - - ushort bios_ctrl; /* 12 BIOS control bits */ - /* bit 0 BIOS don't act as initiator. */ - /* bit 1 BIOS > 1 GB support */ - /* bit 2 BIOS > 2 Disk Support */ - /* bit 3 BIOS don't support removables */ - /* bit 4 BIOS support bootable CD */ - /* bit 5 BIOS scan enabled */ - /* bit 6 BIOS support multiple LUNs */ - /* bit 7 BIOS display of message */ - /* bit 8 SCAM disabled */ - /* bit 9 Reset SCSI bus during init. */ - /* bit 10 Basic Integrity Checking disabled */ - /* bit 11 No verbose initialization. */ - /* bit 12 SCSI parity enabled */ - /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */ - /* bit 14 */ - /* bit 15 */ - ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */ - ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */ - uchar max_host_qng; /* 15 maximum host queueing */ - uchar max_dvc_qng; /* maximum per device queuing */ - ushort dvc_cntl; /* 16 control bit for driver */ - ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */ - ushort serial_number_word1; /* 18 Board serial number word 1 */ - ushort serial_number_word2; /* 19 Board serial number word 2 */ - ushort serial_number_word3; /* 20 Board serial number word 3 */ - ushort check_sum; /* 21 EEP check sum */ - uchar oem_name[16]; /* 22 OEM name */ - ushort dvc_err_code; /* 30 last device driver error code */ - ushort adv_err_code; /* 31 last uc and Adv Lib error code */ - ushort adv_err_addr; /* 32 last uc error address */ - ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ - ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ - ushort saved_adv_err_addr; /* 35 saved last uc error address */ - ushort reserved36; /* 36 reserved */ - ushort reserved37; /* 37 reserved */ - ushort reserved38; /* 38 reserved */ - ushort reserved39; /* 39 reserved */ - ushort reserved40; /* 40 reserved */ - ushort reserved41; /* 41 reserved */ - ushort reserved42; /* 42 reserved */ - ushort reserved43; /* 43 reserved */ - ushort reserved44; /* 44 reserved */ - ushort reserved45; /* 45 reserved */ - ushort reserved46; /* 46 reserved */ - ushort reserved47; /* 47 reserved */ - ushort reserved48; /* 48 reserved */ - ushort reserved49; /* 49 reserved */ - ushort reserved50; /* 50 reserved */ - ushort reserved51; /* 51 reserved */ - ushort reserved52; /* 52 reserved */ - ushort reserved53; /* 53 reserved */ - ushort reserved54; /* 54 reserved */ - ushort reserved55; /* 55 reserved */ - ushort cisptr_lsw; /* 56 CIS PTR LSW */ - ushort cisprt_msw; /* 57 CIS PTR MSW */ - ushort subsysvid; /* 58 SubSystem Vendor ID */ - ushort subsysid; /* 59 SubSystem ID */ - ushort reserved60; /* 60 reserved */ - ushort reserved61; /* 61 reserved */ - ushort reserved62; /* 62 reserved */ - ushort reserved63; /* 63 reserved */ +typedef struct adveep_38C1600_config { + /* Word Offset, Description */ + + ushort cfg_lsw; /* 00 power up initialization */ + /* bit 11 set - Func. 0 INTB, Func. 1 INTA */ + /* clear - Func. 0 INTA, Func. 1 INTB */ + /* bit 13 set - Load CIS */ + /* bit 14 set - BIOS Enable */ + /* bit 15 set - Big Endian Mode */ + ushort cfg_msw; /* 01 unused */ + ushort disc_enable; /* 02 disconnect enable */ + ushort wdtr_able; /* 03 Wide DTR able */ + ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */ + ushort start_motor; /* 05 send start up motor */ + ushort tagqng_able; /* 06 tag queuing able */ + ushort bios_scan; /* 07 BIOS device control */ + ushort scam_tolerant; /* 08 no scam */ + + uchar adapter_scsi_id; /* 09 Host Adapter ID */ + uchar bios_boot_delay; /* power up wait */ + + uchar scsi_reset_delay; /* 10 reset delay */ + uchar bios_id_lun; /* first boot device scsi id & lun */ + /* high nibble is lun */ + /* low nibble is scsi id */ + + uchar termination_se; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + uchar termination_lvd; /* 11 0 - automatic */ + /* 1 - low off / high off */ + /* 2 - low off / high on */ + /* 3 - low on / high on */ + /* There is no low on / high off */ + + ushort bios_ctrl; /* 12 BIOS control bits */ + /* bit 0 BIOS don't act as initiator. */ + /* bit 1 BIOS > 1 GB support */ + /* bit 2 BIOS > 2 Disk Support */ + /* bit 3 BIOS don't support removables */ + /* bit 4 BIOS support bootable CD */ + /* bit 5 BIOS scan enabled */ + /* bit 6 BIOS support multiple LUNs */ + /* bit 7 BIOS display of message */ + /* bit 8 SCAM disabled */ + /* bit 9 Reset SCSI bus during init. */ + /* bit 10 Basic Integrity Checking disabled */ + /* bit 11 No verbose initialization. */ + /* bit 12 SCSI parity enabled */ + /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */ + /* bit 14 */ + /* bit 15 */ + ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */ + ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */ + uchar max_host_qng; /* 15 maximum host queueing */ + uchar max_dvc_qng; /* maximum per device queuing */ + ushort dvc_cntl; /* 16 control bit for driver */ + ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */ + ushort serial_number_word1; /* 18 Board serial number word 1 */ + ushort serial_number_word2; /* 19 Board serial number word 2 */ + ushort serial_number_word3; /* 20 Board serial number word 3 */ + ushort check_sum; /* 21 EEP check sum */ + uchar oem_name[16]; /* 22 OEM name */ + ushort dvc_err_code; /* 30 last device driver error code */ + ushort adv_err_code; /* 31 last uc and Adv Lib error code */ + ushort adv_err_addr; /* 32 last uc error address */ + ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ + ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ + ushort saved_adv_err_addr; /* 35 saved last uc error address */ + ushort reserved36; /* 36 reserved */ + ushort reserved37; /* 37 reserved */ + ushort reserved38; /* 38 reserved */ + ushort reserved39; /* 39 reserved */ + ushort reserved40; /* 40 reserved */ + ushort reserved41; /* 41 reserved */ + ushort reserved42; /* 42 reserved */ + ushort reserved43; /* 43 reserved */ + ushort reserved44; /* 44 reserved */ + ushort reserved45; /* 45 reserved */ + ushort reserved46; /* 46 reserved */ + ushort reserved47; /* 47 reserved */ + ushort reserved48; /* 48 reserved */ + ushort reserved49; /* 49 reserved */ + ushort reserved50; /* 50 reserved */ + ushort reserved51; /* 51 reserved */ + ushort reserved52; /* 52 reserved */ + ushort reserved53; /* 53 reserved */ + ushort reserved54; /* 54 reserved */ + ushort reserved55; /* 55 reserved */ + ushort cisptr_lsw; /* 56 CIS PTR LSW */ + ushort cisprt_msw; /* 57 CIS PTR MSW */ + ushort subsysvid; /* 58 SubSystem Vendor ID */ + ushort subsysid; /* 59 SubSystem ID */ + ushort reserved60; /* 60 reserved */ + ushort reserved61; /* 61 reserved */ + ushort reserved62; /* 62 reserved */ + ushort reserved63; /* 63 reserved */ } ADVEEP_38C1600_CONFIG; /* @@ -2427,11 +2404,11 @@ typedef struct adveep_38C1600_config #define BIOS_CTRL_SCSI_PARITY 0x1000 #define BIOS_CTRL_AIPP_DIS 0x2000 -#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */ -#define ADV_3550_IOLEN 0x40 /* I/O Port Range in bytes */ +#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */ +#define ADV_3550_IOLEN 0x40 /* I/O Port Range in bytes */ -#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */ -#define ADV_38C0800_IOLEN 0x100 /* I/O Port Range in bytes */ +#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */ +#define ADV_38C0800_IOLEN 0x100 /* I/O Port Range in bytes */ /* * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is @@ -2440,9 +2417,9 @@ typedef struct adveep_38C1600_config * * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory * */ -#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */ -#define ADV_38C1600_IOLEN 0x100 /* I/O Port Range 256 bytes */ -#define ADV_38C1600_MEMLEN 0x1000 /* Memory Range 4KB bytes */ +#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */ +#define ADV_38C1600_IOLEN 0x100 /* I/O Port Range 256 bytes */ +#define ADV_38C1600_MEMLEN 0x1000 /* Memory Range 4KB bytes */ /* * Byte I/O register address from base of 'iop_base'. @@ -2515,39 +2492,39 @@ typedef struct adveep_38C1600_config /* * Word I/O register address from base of 'iop_base'. */ -#define IOPW_CHIP_ID_0 0x00 /* CID0 */ -#define IOPW_CTRL_REG 0x02 /* CC */ -#define IOPW_RAM_ADDR 0x04 /* LA */ -#define IOPW_RAM_DATA 0x06 /* LD */ +#define IOPW_CHIP_ID_0 0x00 /* CID0 */ +#define IOPW_CTRL_REG 0x02 /* CC */ +#define IOPW_RAM_ADDR 0x04 /* LA */ +#define IOPW_RAM_DATA 0x06 /* LD */ #define IOPW_RES_ADDR_08 0x08 -#define IOPW_RISC_CSR 0x0A /* CSR */ -#define IOPW_SCSI_CFG0 0x0C /* CFG0 */ -#define IOPW_SCSI_CFG1 0x0E /* CFG1 */ +#define IOPW_RISC_CSR 0x0A /* CSR */ +#define IOPW_SCSI_CFG0 0x0C /* CFG0 */ +#define IOPW_SCSI_CFG1 0x0E /* CFG1 */ #define IOPW_RES_ADDR_10 0x10 -#define IOPW_SEL_MASK 0x12 /* SM */ +#define IOPW_SEL_MASK 0x12 /* SM */ #define IOPW_RES_ADDR_14 0x14 -#define IOPW_FLASH_ADDR 0x16 /* FA */ +#define IOPW_FLASH_ADDR 0x16 /* FA */ #define IOPW_RES_ADDR_18 0x18 -#define IOPW_EE_CMD 0x1A /* EC */ -#define IOPW_EE_DATA 0x1C /* ED */ -#define IOPW_SFIFO_CNT 0x1E /* SFC */ +#define IOPW_EE_CMD 0x1A /* EC */ +#define IOPW_EE_DATA 0x1C /* ED */ +#define IOPW_SFIFO_CNT 0x1E /* SFC */ #define IOPW_RES_ADDR_20 0x20 -#define IOPW_Q_BASE 0x22 /* QB */ -#define IOPW_QP 0x24 /* QP */ -#define IOPW_IX 0x26 /* IX */ -#define IOPW_SP 0x28 /* SP */ -#define IOPW_PC 0x2A /* PC */ +#define IOPW_Q_BASE 0x22 /* QB */ +#define IOPW_QP 0x24 /* QP */ +#define IOPW_IX 0x26 /* IX */ +#define IOPW_SP 0x28 /* SP */ +#define IOPW_PC 0x2A /* PC */ #define IOPW_RES_ADDR_2C 0x2C #define IOPW_RES_ADDR_2E 0x2E -#define IOPW_SCSI_DATA 0x30 /* SD */ -#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */ -#define IOPW_SCSI_CTRL 0x34 /* SC */ -#define IOPW_HSHK_CFG 0x36 /* HCFG */ -#define IOPW_SXFR_STATUS 0x36 /* SXS */ -#define IOPW_SXFR_CNTL 0x38 /* SXL */ -#define IOPW_SXFR_CNTH 0x3A /* SXH */ +#define IOPW_SCSI_DATA 0x30 /* SD */ +#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */ +#define IOPW_SCSI_CTRL 0x34 /* SC */ +#define IOPW_HSHK_CFG 0x36 /* HCFG */ +#define IOPW_SXFR_STATUS 0x36 /* SXS */ +#define IOPW_SXFR_CNTL 0x38 /* SXL */ +#define IOPW_SXFR_CNTH 0x3A /* SXH */ #define IOPW_RES_ADDR_3C 0x3C -#define IOPW_RFIFO_DATA 0x3E /* RFD */ +#define IOPW_RFIFO_DATA 0x3E /* RFD */ /* * Doubleword I/O register address from base of 'iop_base'. @@ -2621,36 +2598,36 @@ typedef struct adveep_38C1600_config /* * SCSI_CFG0 Register bit definitions */ -#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */ -#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */ -#define EVEN_PARITY 0x1000 /* Select Even Parity */ -#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */ -#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */ -#define PRIM_MODE 0x0100 /* Primitive SCSI mode */ -#define SCAM_EN 0x0080 /* Enable SCAM selection */ -#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */ -#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */ -#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */ -#define OUR_ID 0x000F /* SCSI ID */ +#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */ +#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */ +#define EVEN_PARITY 0x1000 /* Select Even Parity */ +#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */ +#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */ +#define PRIM_MODE 0x0100 /* Primitive SCSI mode */ +#define SCAM_EN 0x0080 /* Enable SCAM selection */ +#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */ +#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */ +#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */ +#define OUR_ID 0x000F /* SCSI ID */ /* * SCSI_CFG1 Register bit definitions */ -#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */ -#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */ -#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */ -#define FILTER_SEL 0x0C00 /* Filter Period Selection */ -#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */ -#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */ -#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */ -#define ACTIVE_DBL 0x0200 /* Disable Active Negation */ -#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */ -#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */ -#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */ -#define TERM_CTL 0x0030 /* External SCSI Termination Bits */ -#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */ -#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */ -#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */ +#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */ +#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */ +#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */ +#define FILTER_SEL 0x0C00 /* Filter Period Selection */ +#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */ +#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */ +#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */ +#define ACTIVE_DBL 0x0200 /* Disable Active Negation */ +#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */ +#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */ +#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */ +#define TERM_CTL 0x0030 /* External SCSI Termination Bits */ +#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */ +#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */ +#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */ /* * Addendum for ASC-38C0800 Chip @@ -2663,24 +2640,23 @@ typedef struct adveep_38C1600_config * Also each ASC-38C1600 function or channel uses only cable bits [5:4] * and [1:0]. Bits [14], [7:6], [3:2] are unused. */ -#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */ -#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */ -#define HVD 0x1000 /* HVD Device Detect */ -#define LVD 0x0800 /* LVD Device Detect */ -#define SE 0x0400 /* SE Device Detect */ -#define TERM_LVD 0x00C0 /* LVD Termination Bits */ -#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */ -#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */ -#define TERM_SE 0x0030 /* SE Termination Bits */ -#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */ -#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */ -#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */ -#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */ -#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */ -#define C_DET_SE 0x0003 /* SE Cable Detect Bits */ -#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */ -#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */ - +#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */ +#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */ +#define HVD 0x1000 /* HVD Device Detect */ +#define LVD 0x0800 /* LVD Device Detect */ +#define SE 0x0400 /* SE Device Detect */ +#define TERM_LVD 0x00C0 /* LVD Termination Bits */ +#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */ +#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */ +#define TERM_SE 0x0030 /* SE Termination Bits */ +#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */ +#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */ +#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */ +#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */ +#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */ +#define C_DET_SE 0x0003 /* SE Cable Detect Bits */ +#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */ +#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */ #define CABLE_ILLEGAL_A 0x7 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */ @@ -2691,39 +2667,39 @@ typedef struct adveep_38C1600_config /* * MEM_CFG Register bit definitions */ -#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */ -#define FAST_EE_CLK 0x20 /* Diagnostic Bit */ -#define RAM_SZ 0x1C /* Specify size of RAM to RISC */ -#define RAM_SZ_2KB 0x00 /* 2 KB */ -#define RAM_SZ_4KB 0x04 /* 4 KB */ -#define RAM_SZ_8KB 0x08 /* 8 KB */ -#define RAM_SZ_16KB 0x0C /* 16 KB */ -#define RAM_SZ_32KB 0x10 /* 32 KB */ -#define RAM_SZ_64KB 0x14 /* 64 KB */ +#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */ +#define FAST_EE_CLK 0x20 /* Diagnostic Bit */ +#define RAM_SZ 0x1C /* Specify size of RAM to RISC */ +#define RAM_SZ_2KB 0x00 /* 2 KB */ +#define RAM_SZ_4KB 0x04 /* 4 KB */ +#define RAM_SZ_8KB 0x08 /* 8 KB */ +#define RAM_SZ_16KB 0x0C /* 16 KB */ +#define RAM_SZ_32KB 0x10 /* 32 KB */ +#define RAM_SZ_64KB 0x14 /* 64 KB */ /* * DMA_CFG0 Register bit definitions * * This register is only accessible to the host. */ -#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */ -#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */ -#define FIFO_THRESH_16B 0x00 /* 16 bytes */ -#define FIFO_THRESH_32B 0x20 /* 32 bytes */ -#define FIFO_THRESH_48B 0x30 /* 48 bytes */ -#define FIFO_THRESH_64B 0x40 /* 64 bytes */ -#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */ -#define FIFO_THRESH_96B 0x60 /* 96 bytes */ -#define FIFO_THRESH_112B 0x70 /* 112 bytes */ -#define START_CTL 0x0C /* DMA start conditions */ -#define START_CTL_TH 0x00 /* Wait threshold level (default) */ -#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */ -#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */ -#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */ -#define READ_CMD 0x03 /* Memory Read Method */ -#define READ_CMD_MR 0x00 /* Memory Read */ -#define READ_CMD_MRL 0x02 /* Memory Read Long */ -#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */ +#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */ +#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */ +#define FIFO_THRESH_16B 0x00 /* 16 bytes */ +#define FIFO_THRESH_32B 0x20 /* 32 bytes */ +#define FIFO_THRESH_48B 0x30 /* 48 bytes */ +#define FIFO_THRESH_64B 0x40 /* 64 bytes */ +#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */ +#define FIFO_THRESH_96B 0x60 /* 96 bytes */ +#define FIFO_THRESH_112B 0x70 /* 112 bytes */ +#define START_CTL 0x0C /* DMA start conditions */ +#define START_CTL_TH 0x00 /* Wait threshold level (default) */ +#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */ +#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */ +#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */ +#define READ_CMD 0x03 /* Memory Read Method */ +#define READ_CMD_MR 0x00 /* Memory Read */ +#define READ_CMD_MRL 0x02 /* Memory Read Long */ +#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */ /* * ASC-38C0800 RAM BIST Register bit definitions @@ -2747,7 +2723,7 @@ typedef struct adveep_38C1600_config * IOPB_PCI_INT_CFG Bit Field Definitions */ -#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */ +#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */ /* * Bit 1 can be set to change the interrupt for the Function to operate in @@ -2780,53 +2756,52 @@ typedef struct adveep_38C1600_config #define ADV_BUSY 0 #define ADV_ERROR (-1) - /* * ADV_DVC_VAR 'warn_code' values */ -#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */ -#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */ -#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */ -#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */ -#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */ +#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */ +#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */ +#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */ +#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */ +#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */ -#define ADV_MAX_TID 15 /* max. target identifier */ -#define ADV_MAX_LUN 7 /* max. logical unit number */ +#define ADV_MAX_TID 15 /* max. target identifier */ +#define ADV_MAX_LUN 7 /* max. logical unit number */ /* * Error code values are set in ADV_DVC_VAR 'err_code'. */ -#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */ -#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */ -#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */ -#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */ -#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */ -#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */ -#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */ -#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */ -#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */ -#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */ -#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */ -#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */ -#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */ -#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */ +#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */ +#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */ +#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */ +#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */ +#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */ +#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */ +#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */ +#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */ +#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */ +#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */ +#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */ +#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */ +#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */ +#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */ /* * Fixed locations of microcode operating variables. */ -#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */ -#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */ -#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */ -#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */ -#define ASC_MC_VERSION_NUM 0x003A /* microcode number */ -#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */ -#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */ -#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */ -#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */ -#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */ -#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */ -#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */ -#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */ +#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */ +#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */ +#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */ +#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */ +#define ASC_MC_VERSION_NUM 0x003A /* microcode number */ +#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */ +#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */ +#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */ +#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */ +#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */ +#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */ +#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */ +#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */ #define ASC_MC_CHIP_TYPE 0x009A #define ASC_MC_INTRB_CODE 0x009B #define ASC_MC_WDTR_ABLE 0x009C @@ -2844,9 +2819,9 @@ typedef struct adveep_38C1600_config #define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0 #define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0 #define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100 -#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */ +#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */ #define ASC_MC_WDTR_DONE 0x0124 -#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */ +#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */ #define ASC_MC_ICQ 0x0160 #define ASC_MC_IRQ 0x0164 #define ASC_MC_PPR_ABLE 0x017A @@ -2865,8 +2840,8 @@ typedef struct adveep_38C1600_config * Flags set by the Adv Library in RISC variable 'control_flag' (0x122) * and handled by the microcode. */ -#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */ -#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */ +#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */ +#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */ /* * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format @@ -2875,45 +2850,44 @@ typedef struct adveep_38C1600_config #define HSHK_CFG_RATE 0x0F00 #define HSHK_CFG_OFFSET 0x001F -#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */ -#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */ -#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */ -#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */ - -#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */ -#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */ -#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */ -#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */ -#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */ - -#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */ -#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */ -#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */ -#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */ -#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */ +#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */ +#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */ +#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */ +#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */ + +#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */ +#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */ +#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */ +#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */ +#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */ + +#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */ +#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */ +#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */ +#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */ +#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */ /* * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used. */ -#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */ -#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */ +#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */ +#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */ /* * All fields here are accessed by the board microcode and need to be * little-endian. */ -typedef struct adv_carr_t -{ - ADV_VADDR carr_va; /* Carrier Virtual Address */ - ADV_PADDR carr_pa; /* Carrier Physical Address */ - ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */ - /* - * next_vpa [31:4] Carrier Virtual or Physical Next Pointer - * - * next_vpa [3:1] Reserved Bits - * next_vpa [0] Done Flag set in Response Queue. - */ - ADV_VADDR next_vpa; +typedef struct adv_carr_t { + ADV_VADDR carr_va; /* Carrier Virtual Address */ + ADV_PADDR carr_pa; /* Carrier Physical Address */ + ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */ + /* + * next_vpa [31:4] Carrier Virtual or Physical Next Pointer + * + * next_vpa [3:1] Reserved Bits + * next_vpa [0] Done Flag set in Response Queue. + */ + ADV_VADDR next_vpa; } ADV_CARR_T; /* @@ -2940,13 +2914,13 @@ typedef struct adv_carr_t * The Adv Library should limit use to the lower nibble (4 bits) of * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag. */ -#define ADV_POLL_REQUEST 0x01 /* poll for request completion */ -#define ADV_SCSIQ_DONE 0x02 /* request done */ -#define ADV_DONT_RETRY 0x08 /* don't do retry */ +#define ADV_POLL_REQUEST 0x01 /* poll for request completion */ +#define ADV_SCSIQ_DONE 0x02 /* request done */ +#define ADV_DONT_RETRY 0x08 /* don't do retry */ -#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */ -#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */ -#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */ +#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */ +#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */ +#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */ /* * Adapter temporary configuration structure @@ -2960,30 +2934,30 @@ typedef struct adv_carr_t * value of the field is never reset. */ typedef struct adv_dvc_cfg { - ushort disc_enable; /* enable disconnection */ - uchar chip_version; /* chip version */ - uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */ - ushort lib_version; /* Adv Library version number */ - ushort control_flag; /* Microcode Control Flag */ - ushort mcode_date; /* Microcode date */ - ushort mcode_version; /* Microcode version */ - ushort pci_slot_info; /* high byte device/function number */ - /* bits 7-3 device num., bits 2-0 function num. */ - /* low byte bus num. */ - ushort serial1; /* EEPROM serial number word 1 */ - ushort serial2; /* EEPROM serial number word 2 */ - ushort serial3; /* EEPROM serial number word 3 */ - struct device *dev; /* pointer to the pci dev structure for this board */ + ushort disc_enable; /* enable disconnection */ + uchar chip_version; /* chip version */ + uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */ + ushort lib_version; /* Adv Library version number */ + ushort control_flag; /* Microcode Control Flag */ + ushort mcode_date; /* Microcode date */ + ushort mcode_version; /* Microcode version */ + ushort pci_slot_info; /* high byte device/function number */ + /* bits 7-3 device num., bits 2-0 function num. */ + /* low byte bus num. */ + ushort serial1; /* EEPROM serial number word 1 */ + ushort serial2; /* EEPROM serial number word 2 */ + ushort serial3; /* EEPROM serial number word 3 */ + struct device *dev; /* pointer to the pci dev structure for this board */ } ADV_DVC_CFG; struct adv_dvc_var; struct adv_scsi_req_q; -typedef void (* ADV_ISR_CALLBACK) - (struct adv_dvc_var *, struct adv_scsi_req_q *); +typedef void (*ADV_ISR_CALLBACK) + (struct adv_dvc_var *, struct adv_scsi_req_q *); -typedef void (* ADV_ASYNC_CALLBACK) - (struct adv_dvc_var *, uchar); +typedef void (*ADV_ASYNC_CALLBACK) + (struct adv_dvc_var *, uchar); /* * Adapter operation variable structure. @@ -2998,55 +2972,55 @@ typedef void (* ADV_ASYNC_CALLBACK) * of the feature, the field is cleared. */ typedef struct adv_dvc_var { - AdvPortAddr iop_base; /* I/O port address */ - ushort err_code; /* fatal error code */ - ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */ - ADV_ISR_CALLBACK isr_callback; - ADV_ASYNC_CALLBACK async_callback; - ushort wdtr_able; /* try WDTR for a device */ - ushort sdtr_able; /* try SDTR for a device */ - ushort ultra_able; /* try SDTR Ultra speed for a device */ - ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */ - ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */ - ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */ - ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */ - ushort tagqng_able; /* try tagged queuing with a device */ - ushort ppr_able; /* PPR message capable per TID bitmask. */ - uchar max_dvc_qng; /* maximum number of tagged commands per device */ - ushort start_motor; /* start motor command allowed */ - uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */ - uchar chip_no; /* should be assigned by caller */ - uchar max_host_qng; /* maximum number of Q'ed command allowed */ - uchar irq_no; /* IRQ number */ - ushort no_scam; /* scam_tolerant of EEPROM */ - struct asc_board *drv_ptr; /* driver pointer to private structure */ - uchar chip_scsi_id; /* chip SCSI target ID */ - uchar chip_type; - uchar bist_err_code; - ADV_CARR_T *carrier_buf; - ADV_CARR_T *carr_freelist; /* Carrier free list. */ - ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */ - ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */ - ushort carr_pending_cnt; /* Count of pending carriers. */ - /* - * Note: The following fields will not be used after initialization. The - * driver may discard the buffer after initialization is done. - */ - ADV_DVC_CFG *cfg; /* temporary configuration structure */ + AdvPortAddr iop_base; /* I/O port address */ + ushort err_code; /* fatal error code */ + ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */ + ADV_ISR_CALLBACK isr_callback; + ADV_ASYNC_CALLBACK async_callback; + ushort wdtr_able; /* try WDTR for a device */ + ushort sdtr_able; /* try SDTR for a device */ + ushort ultra_able; /* try SDTR Ultra speed for a device */ + ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */ + ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */ + ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */ + ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */ + ushort tagqng_able; /* try tagged queuing with a device */ + ushort ppr_able; /* PPR message capable per TID bitmask. */ + uchar max_dvc_qng; /* maximum number of tagged commands per device */ + ushort start_motor; /* start motor command allowed */ + uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */ + uchar chip_no; /* should be assigned by caller */ + uchar max_host_qng; /* maximum number of Q'ed command allowed */ + uchar irq_no; /* IRQ number */ + ushort no_scam; /* scam_tolerant of EEPROM */ + struct asc_board *drv_ptr; /* driver pointer to private structure */ + uchar chip_scsi_id; /* chip SCSI target ID */ + uchar chip_type; + uchar bist_err_code; + ADV_CARR_T *carrier_buf; + ADV_CARR_T *carr_freelist; /* Carrier free list. */ + ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */ + ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */ + ushort carr_pending_cnt; /* Count of pending carriers. */ + /* + * Note: The following fields will not be used after initialization. The + * driver may discard the buffer after initialization is done. + */ + ADV_DVC_CFG *cfg; /* temporary configuration structure */ } ADV_DVC_VAR; #define NO_OF_SG_PER_BLOCK 15 typedef struct asc_sg_block { - uchar reserved1; - uchar reserved2; - uchar reserved3; - uchar sg_cnt; /* Valid entries in block. */ - ADV_PADDR sg_ptr; /* Pointer to next sg block. */ - struct { - ADV_PADDR sg_addr; /* SG element address. */ - ADV_DCNT sg_count; /* SG element count. */ - } sg_list[NO_OF_SG_PER_BLOCK]; + uchar reserved1; + uchar reserved2; + uchar reserved3; + uchar sg_cnt; /* Valid entries in block. */ + ADV_PADDR sg_ptr; /* Pointer to next sg block. */ + struct { + ADV_PADDR sg_addr; /* SG element address. */ + ADV_DCNT sg_count; /* SG element count. */ + } sg_list[NO_OF_SG_PER_BLOCK]; } ADV_SG_BLOCK; /* @@ -3061,37 +3035,37 @@ typedef struct asc_sg_block { * order. */ typedef struct adv_scsi_req_q { - uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */ - uchar target_cmd; - uchar target_id; /* Device target identifier. */ - uchar target_lun; /* Device target logical unit number. */ - ADV_PADDR data_addr; /* Data buffer physical address. */ - ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */ - ADV_PADDR sense_addr; - ADV_PADDR carr_pa; - uchar mflag; - uchar sense_len; - uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */ - uchar scsi_cntl; - uchar done_status; /* Completion status. */ - uchar scsi_status; /* SCSI status byte. */ - uchar host_status; /* Ucode host status. */ - uchar sg_working_ix; - uchar cdb[12]; /* SCSI CDB bytes 0-11. */ - ADV_PADDR sg_real_addr; /* SG list physical address. */ - ADV_PADDR scsiq_rptr; - uchar cdb16[4]; /* SCSI CDB bytes 12-15. */ - ADV_VADDR scsiq_ptr; - ADV_VADDR carr_va; - /* - * End of microcode structure - 60 bytes. The rest of the structure - * is used by the Adv Library and ignored by the microcode. - */ - ADV_VADDR srb_ptr; - ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */ - char *vdata_addr; /* Data buffer virtual address. */ - uchar a_flag; - uchar pad[2]; /* Pad out to a word boundary. */ + uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */ + uchar target_cmd; + uchar target_id; /* Device target identifier. */ + uchar target_lun; /* Device target logical unit number. */ + ADV_PADDR data_addr; /* Data buffer physical address. */ + ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */ + ADV_PADDR sense_addr; + ADV_PADDR carr_pa; + uchar mflag; + uchar sense_len; + uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */ + uchar scsi_cntl; + uchar done_status; /* Completion status. */ + uchar scsi_status; /* SCSI status byte. */ + uchar host_status; /* Ucode host status. */ + uchar sg_working_ix; + uchar cdb[12]; /* SCSI CDB bytes 0-11. */ + ADV_PADDR sg_real_addr; /* SG list physical address. */ + ADV_PADDR scsiq_rptr; + uchar cdb16[4]; /* SCSI CDB bytes 12-15. */ + ADV_VADDR scsiq_ptr; + ADV_VADDR carr_va; + /* + * End of microcode structure - 60 bytes. The rest of the structure + * is used by the Adv Library and ignored by the microcode. + */ + ADV_VADDR srb_ptr; + ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */ + char *vdata_addr; /* Data buffer virtual address. */ + uchar a_flag; + uchar pad[2]; /* Pad out to a word boundary. */ } ADV_SCSI_REQ_Q; /* @@ -3103,8 +3077,8 @@ typedef struct adv_scsi_req_q { #define IDLE_CMD_SEND_INT 0x0004 #define IDLE_CMD_ABORT 0x0008 #define IDLE_CMD_DEVICE_RESET 0x0010 -#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */ -#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */ +#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */ +#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */ #define IDLE_CMD_SCSIREQ 0x0080 #define IDLE_CMD_STATUS_SUCCESS 0x0001 @@ -3118,60 +3092,59 @@ typedef struct adv_scsi_req_q { /* * Wait loop time out values. */ -#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */ -#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */ -#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */ -#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */ -#define SCSI_MAX_RETRY 10 /* retry count */ - -#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */ -#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */ -#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */ -#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */ +#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */ +#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */ +#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */ +#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */ +#define SCSI_MAX_RETRY 10 /* retry count */ +#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */ +#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */ +#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */ +#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */ -#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */ +#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */ /* * Device drivers must define the following functions. */ -STATIC inline ulong DvcEnterCritical(void); -STATIC inline void DvcLeaveCritical(ulong); -STATIC void DvcSleepMilliSecond(ADV_DCNT); -STATIC uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort); -STATIC void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar); -STATIC ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, - uchar *, ASC_SDCNT *, int); -STATIC void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort); +static inline ulong DvcEnterCritical(void); +static inline void DvcLeaveCritical(ulong); +static void DvcSleepMilliSecond(ADV_DCNT); +static uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort); +static void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar); +static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, + uchar *, ASC_SDCNT *, int); +static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort); /* * Adv Library functions available to drivers. */ -STATIC int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -STATIC int AdvISR(ADV_DVC_VAR *); -STATIC int AdvInitGetConfig(ADV_DVC_VAR *); -STATIC int AdvInitAsc3550Driver(ADV_DVC_VAR *); -STATIC int AdvInitAsc38C0800Driver(ADV_DVC_VAR *); -STATIC int AdvInitAsc38C1600Driver(ADV_DVC_VAR *); -STATIC int AdvResetChipAndSB(ADV_DVC_VAR *); -STATIC int AdvResetSB(ADV_DVC_VAR *asc_dvc); +static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); +static int AdvISR(ADV_DVC_VAR *); +static int AdvInitGetConfig(ADV_DVC_VAR *); +static int AdvInitAsc3550Driver(ADV_DVC_VAR *); +static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *); +static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *); +static int AdvResetChipAndSB(ADV_DVC_VAR *); +static int AdvResetSB(ADV_DVC_VAR *asc_dvc); /* * Internal Adv Library functions. */ -STATIC int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT); -STATIC void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -STATIC int AdvInitFrom3550EEP(ADV_DVC_VAR *); -STATIC int AdvInitFrom38C0800EEP(ADV_DVC_VAR *); -STATIC int AdvInitFrom38C1600EEP(ADV_DVC_VAR *); -STATIC ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); -STATIC void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); -STATIC ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); -STATIC void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); -STATIC ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); -STATIC void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); -STATIC void AdvWaitEEPCmd(AdvPortAddr); -STATIC ushort AdvReadEEPWord(AdvPortAddr, int); +static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT); +static void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); +static int AdvInitFrom3550EEP(ADV_DVC_VAR *); +static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *); +static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *); +static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); +static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); +static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); +static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); +static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); +static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); +static void AdvWaitEEPCmd(AdvPortAddr); +static ushort AdvReadEEPWord(AdvPortAddr, int); /* * PCI Bus Definitions @@ -3241,7 +3214,6 @@ do { \ #define AdvWriteWordAutoIncLram(iop_base, word) \ (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word))) - /* * Define macro to check for Condor signature. * @@ -3313,7 +3285,7 @@ do { \ * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values. */ -#define QD_NO_STATUS 0x00 /* Request not completed yet. */ +#define QD_NO_STATUS 0x00 /* Request not completed yet. */ #define QD_NO_ERROR 0x01 #define QD_ABORTED_BY_HOST 0x02 #define QD_WITH_ERROR 0x04 @@ -3323,30 +3295,29 @@ do { \ #define QHSTA_M_DATA_OVER_RUN 0x12 #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13 #define QHSTA_M_QUEUE_ABORTED 0x15 -#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */ -#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */ -#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */ -#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */ -#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */ -#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */ -#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */ +#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */ +#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */ +#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */ +#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */ +#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */ +#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */ +#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */ /* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */ -#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */ -#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */ -#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */ -#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */ -#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */ -#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */ -#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */ -#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */ +#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */ +#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */ +#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */ +#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */ +#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */ +#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */ +#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */ +#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */ #define QHSTA_M_WTM_TIMEOUT 0x41 #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42 #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43 #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44 -#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */ -#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */ -#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */ - +#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */ +#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */ +#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */ /* * Default EEPROM Configuration structure defined in a_init.c. @@ -3358,12 +3329,12 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config; /* * DvcGetPhyAddr() flag arguments */ -#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */ -#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */ -#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */ -#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */ -#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */ -#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */ +#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */ +#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */ +#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */ +#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */ +#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */ +#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */ /* Return the address that is aligned at the next doubleword >= to 'addr'. */ #define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7) @@ -3413,43 +3384,42 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config; #define ADV_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2) typedef struct { - uchar periph; /* peripheral device type [0:4] */ - /* peripheral qualifier [5:7] */ - uchar devtype; /* device type modifier (for SCSI I) [0:6] */ - /* RMB - removable medium bit [7] */ - uchar ver; /* ANSI approved version [0:2] */ - /* ECMA version [3:5] */ - /* ISO version [6:7] */ - uchar byte3; /* response data format [0:3] */ - /* 0 SCSI 1 */ - /* 1 CCS */ - /* 2 SCSI-2 */ - /* 3-F reserved */ - /* reserved [4:5] */ - /* terminate I/O process bit (see 5.6.22) [6] */ - /* asynch. event notification (processor) [7] */ - uchar add_len; /* additional length */ - uchar res1; /* reserved */ - uchar res2; /* reserved */ - uchar flags; /* soft reset implemented [0] */ - /* command queuing [1] */ - /* reserved [2] */ - /* linked command for this logical unit [3] */ - /* synchronous data transfer [4] */ - /* wide bus 16 bit data transfer [5] */ - /* wide bus 32 bit data transfer [6] */ - /* relative addressing mode [7] */ - uchar vendor_id[8]; /* vendor identification */ - uchar product_id[16]; /* product identification */ - uchar product_rev_level[4]; /* product revision level */ - uchar vendor_specific[20]; /* vendor specific */ - uchar info; /* information unit supported [0] */ - /* quick arbitrate supported [1] */ - /* clocking field [2:3] */ - /* reserved [4:7] */ - uchar res3; /* reserved */ -} ADV_SCSI_INQUIRY; /* 58 bytes */ - + uchar periph; /* peripheral device type [0:4] */ + /* peripheral qualifier [5:7] */ + uchar devtype; /* device type modifier (for SCSI I) [0:6] */ + /* RMB - removable medium bit [7] */ + uchar ver; /* ANSI approved version [0:2] */ + /* ECMA version [3:5] */ + /* ISO version [6:7] */ + uchar byte3; /* response data format [0:3] */ + /* 0 SCSI 1 */ + /* 1 CCS */ + /* 2 SCSI-2 */ + /* 3-F reserved */ + /* reserved [4:5] */ + /* terminate I/O process bit (see 5.6.22) [6] */ + /* asynch. event notification (processor) [7] */ + uchar add_len; /* additional length */ + uchar res1; /* reserved */ + uchar res2; /* reserved */ + uchar flags; /* soft reset implemented [0] */ + /* command queuing [1] */ + /* reserved [2] */ + /* linked command for this logical unit [3] */ + /* synchronous data transfer [4] */ + /* wide bus 16 bit data transfer [5] */ + /* wide bus 32 bit data transfer [6] */ + /* relative addressing mode [7] */ + uchar vendor_id[8]; /* vendor identification */ + uchar product_id[16]; /* product identification */ + uchar product_rev_level[4]; /* product revision level */ + uchar vendor_specific[20]; /* vendor specific */ + uchar info; /* information unit supported [0] */ + /* quick arbitrate supported [1] */ + /* clocking field [2:3] */ + /* reserved [4:7] */ + uchar res3; /* reserved */ +} ADV_SCSI_INQUIRY; /* 58 bytes */ /* * --- Driver Constants and Macros @@ -3464,15 +3434,15 @@ typedef struct { /* asc_board_t flags */ #define ASC_HOST_IN_RESET 0x01 -#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */ +#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */ #define ASC_SELECT_QUEUE_DEPTHS 0x08 #define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0) #define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD) -#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */ +#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */ -#define ASC_INFO_SIZE 128 /* advansys_info() line size */ +#define ASC_INFO_SIZE 128 /* advansys_info() line size */ #ifdef CONFIG_PROC_FS /* /proc/scsi/advansys/[0...] related definitions */ @@ -3514,7 +3484,7 @@ typedef struct { * REQPTIME(reqp) - reqp's time stamp value * REQTIMESTAMP() - system time stamp value */ -typedef struct scsi_cmnd REQ, *REQP; +typedef struct scsi_cmnd REQ, *REQP; #define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble)) #define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble)) #define REQPTID(reqp) ((reqp)->device->id) @@ -3564,17 +3534,17 @@ typedef struct scsi_cmnd REQ, *REQP; #define PCI_MAX_SLOT 0x1F #define PCI_MAX_BUS 0xFF #define PCI_IOADDRESS_MASK 0xFFFE -#define ASC_PCI_DEVICE_ID_CNT 6 /* PCI Device ID count. */ +#define ASC_PCI_DEVICE_ID_CNT 6 /* PCI Device ID count. */ #ifndef ADVANSYS_STATS -#define ASC_STATS(shp, counter) -#define ASC_STATS_ADD(shp, counter, count) +#define ASC_STATS(shost, counter) +#define ASC_STATS_ADD(shost, counter, count) #else /* ADVANSYS_STATS */ -#define ASC_STATS(shp, counter) \ - (ASC_BOARDP(shp)->asc_stats.counter++) +#define ASC_STATS(shost, counter) \ + (ASC_BOARDP(shost)->asc_stats.counter++) -#define ASC_STATS_ADD(shp, counter, count) \ - (ASC_BOARDP(shp)->asc_stats.counter += (count)) +#define ASC_STATS_ADD(shost, counter, count) \ + (ASC_BOARDP(shost)->asc_stats.counter += (count)) #endif /* ADVANSYS_STATS */ #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit)) @@ -3617,7 +3587,6 @@ typedef struct scsi_cmnd REQ, *REQP; printk((s), (a1), (a2), (a3), (a4)); \ } - #ifndef ADVANSYS_DEBUG #define ASC_DBG(lvl, s) @@ -3746,7 +3715,6 @@ typedef struct scsi_cmnd REQ, *REQP; #endif /* ADVANSYS_ASSERT */ - /* * --- Driver Structures */ @@ -3755,27 +3723,27 @@ typedef struct scsi_cmnd REQ, *REQP; /* Per board statistics structure */ struct asc_stats { - /* Driver Entrypoint Statistics */ - ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */ - ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */ - ADV_DCNT biosparam; /* # calls to advansys_biosparam() */ - ADV_DCNT interrupt; /* # advansys_interrupt() calls */ - ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */ - ADV_DCNT done; /* # calls to request's scsi_done function */ - ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */ - ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */ - ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */ - /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */ - ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */ - ADV_DCNT exe_busy; /* # ASC_BUSY returns. */ - ADV_DCNT exe_error; /* # ASC_ERROR returns. */ - ADV_DCNT exe_unknown; /* # unknown returns. */ - /* Data Transfer Statistics */ - ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */ - ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */ - ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */ - ADV_DCNT sg_elem; /* # scatter-gather elements */ - ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */ + /* Driver Entrypoint Statistics */ + ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */ + ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */ + ADV_DCNT biosparam; /* # calls to advansys_biosparam() */ + ADV_DCNT interrupt; /* # advansys_interrupt() calls */ + ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */ + ADV_DCNT done; /* # calls to request's scsi_done function */ + ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */ + ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */ + ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */ + /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */ + ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */ + ADV_DCNT exe_busy; /* # ASC_BUSY returns. */ + ADV_DCNT exe_error; /* # ASC_ERROR returns. */ + ADV_DCNT exe_unknown; /* # unknown returns. */ + /* Data Transfer Statistics */ + ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */ + ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */ + ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */ + ADV_DCNT sg_elem; /* # scatter-gather elements */ + ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */ }; #endif /* ADVANSYS_STATS */ @@ -3783,17 +3751,17 @@ struct asc_stats { * Request queuing structure */ typedef struct asc_queue { - ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */ - REQP q_first[ADV_MAX_TID+1]; /* first queued request */ - REQP q_last[ADV_MAX_TID+1]; /* last queued request */ + ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */ + REQP q_first[ADV_MAX_TID + 1]; /* first queued request */ + REQP q_last[ADV_MAX_TID + 1]; /* last queued request */ #ifdef ADVANSYS_STATS - short q_cur_cnt[ADV_MAX_TID+1]; /* current queue count */ - short q_max_cnt[ADV_MAX_TID+1]; /* maximum queue count */ - ADV_DCNT q_tot_cnt[ADV_MAX_TID+1]; /* total enqueue count */ - ADV_DCNT q_tot_tim[ADV_MAX_TID+1]; /* total time queued */ - ushort q_max_tim[ADV_MAX_TID+1]; /* maximum time queued */ - ushort q_min_tim[ADV_MAX_TID+1]; /* minimum time queued */ -#endif /* ADVANSYS_STATS */ + short q_cur_cnt[ADV_MAX_TID + 1]; /* current queue count */ + short q_max_cnt[ADV_MAX_TID + 1]; /* maximum queue count */ + ADV_DCNT q_tot_cnt[ADV_MAX_TID + 1]; /* total enqueue count */ + ADV_DCNT q_tot_tim[ADV_MAX_TID + 1]; /* total time queued */ + ushort q_max_tim[ADV_MAX_TID + 1]; /* maximum time queued */ + ushort q_min_tim[ADV_MAX_TID + 1]; /* minimum time queued */ +#endif /* ADVANSYS_STATS */ } asc_queue_t; /* @@ -3814,17 +3782,17 @@ typedef struct asc_queue { * Both structures must be 32 byte aligned. */ typedef struct adv_sgblk { - ADV_SG_BLOCK sg_block; /* Sgblock structure. */ - uchar align[32]; /* Sgblock structure padding. */ - struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */ + ADV_SG_BLOCK sg_block; /* Sgblock structure. */ + uchar align[32]; /* Sgblock structure padding. */ + struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */ } adv_sgblk_t; typedef struct adv_req { - ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */ - uchar align[32]; /* Request structure padding. */ - struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */ - adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */ - struct adv_req *next_reqp; /* Next Request Structure. */ + ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */ + uchar align[32]; /* Request structure padding. */ + struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */ + adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */ + struct adv_req *next_reqp; /* Next Request Structure. */ } adv_req_t; /* @@ -3835,113 +3803,109 @@ typedef struct adv_req { * field. It is guaranteed to be allocated from DMA-able memory. */ typedef struct asc_board { - int id; /* Board Id */ - uint flags; /* Board flags */ - union { - ASC_DVC_VAR asc_dvc_var; /* Narrow board */ - ADV_DVC_VAR adv_dvc_var; /* Wide board */ - } dvc_var; - union { - ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */ - ADV_DVC_CFG adv_dvc_cfg; /* Wide board */ - } dvc_cfg; - ushort asc_n_io_port; /* Number I/O ports. */ - asc_queue_t active; /* Active command queue */ - asc_queue_t waiting; /* Waiting command queue */ - asc_queue_t done; /* Done command queue */ - ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ - struct scsi_device *device[ADV_MAX_TID+1]; /* Mid-Level Scsi Device */ - ushort reqcnt[ADV_MAX_TID+1]; /* Starvation request count */ - ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */ - ushort queue_full_cnt[ADV_MAX_TID+1]; /* Queue full count */ - union { - ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */ - ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */ - ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */ - ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */ - } eep_config; - ulong last_reset; /* Saved last reset time */ - spinlock_t lock; /* Board spinlock */ + int id; /* Board Id */ + uint flags; /* Board flags */ + union { + ASC_DVC_VAR asc_dvc_var; /* Narrow board */ + ADV_DVC_VAR adv_dvc_var; /* Wide board */ + } dvc_var; + union { + ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */ + ADV_DVC_CFG adv_dvc_cfg; /* Wide board */ + } dvc_cfg; + ushort asc_n_io_port; /* Number I/O ports. */ + asc_queue_t active; /* Active command queue */ + asc_queue_t waiting; /* Waiting command queue */ + asc_queue_t done; /* Done command queue */ + ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ + struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */ + ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */ + ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */ + ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */ + union { + ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */ + ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */ + ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */ + ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */ + } eep_config; + ulong last_reset; /* Saved last reset time */ + spinlock_t lock; /* Board spinlock */ #ifdef CONFIG_PROC_FS - /* /proc/scsi/advansys/[0...] */ - char *prtbuf; /* /proc print buffer */ -#endif /* CONFIG_PROC_FS */ + /* /proc/scsi/advansys/[0...] */ + char *prtbuf; /* /proc print buffer */ +#endif /* CONFIG_PROC_FS */ #ifdef ADVANSYS_STATS - struct asc_stats asc_stats; /* Board statistics */ -#endif /* ADVANSYS_STATS */ - /* - * The following fields are used only for Narrow Boards. - */ - /* The following three structures must be in DMA-able memory. */ - ASC_SCSI_REQ_Q scsireqq; - ASC_CAP_INFO cap_info; - ASC_SCSI_INQUIRY inquiry; - uchar sdtr_data[ASC_MAX_TID+1]; /* SDTR information */ - /* - * The following fields are used only for Wide Boards. - */ - void __iomem *ioremap_addr; /* I/O Memory remap address. */ - ushort ioport; /* I/O Port address. */ - ADV_CARR_T *orig_carrp; /* ADV_CARR_T memory block. */ - adv_req_t *orig_reqp; /* adv_req_t memory block. */ - adv_req_t *adv_reqp; /* Request structures. */ - adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */ - ushort bios_signature; /* BIOS Signature. */ - ushort bios_version; /* BIOS Version. */ - ushort bios_codeseg; /* BIOS Code Segment. */ - ushort bios_codelen; /* BIOS Code Segment Length. */ + struct asc_stats asc_stats; /* Board statistics */ +#endif /* ADVANSYS_STATS */ + /* + * The following fields are used only for Narrow Boards. + */ + /* The following three structures must be in DMA-able memory. */ + ASC_SCSI_REQ_Q scsireqq; + ASC_CAP_INFO cap_info; + ASC_SCSI_INQUIRY inquiry; + uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */ + /* + * The following fields are used only for Wide Boards. + */ + void __iomem *ioremap_addr; /* I/O Memory remap address. */ + ushort ioport; /* I/O Port address. */ + ADV_CARR_T *orig_carrp; /* ADV_CARR_T memory block. */ + adv_req_t *orig_reqp; /* adv_req_t memory block. */ + adv_req_t *adv_reqp; /* Request structures. */ + adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */ + ushort bios_signature; /* BIOS Signature. */ + ushort bios_version; /* BIOS Version. */ + ushort bios_codeseg; /* BIOS Code Segment. */ + ushort bios_codelen; /* BIOS Code Segment Length. */ } asc_board_t; /* * PCI configuration structures */ -typedef struct _PCI_DATA_ -{ - uchar type; - uchar bus; - uchar slot; - uchar func; - uchar offset; +typedef struct _PCI_DATA_ { + uchar type; + uchar bus; + uchar slot; + uchar func; + uchar offset; } PCI_DATA; -typedef struct _PCI_DEVICE_ -{ - ushort vendorID; - ushort deviceID; - ushort slotNumber; - ushort slotFound; - uchar busNumber; - uchar maxBusNumber; - uchar devFunc; - ushort startSlot; - ushort endSlot; - uchar bridge; - uchar type; +typedef struct _PCI_DEVICE_ { + ushort vendorID; + ushort deviceID; + ushort slotNumber; + ushort slotFound; + uchar busNumber; + uchar maxBusNumber; + uchar devFunc; + ushort startSlot; + ushort endSlot; + uchar bridge; + uchar type; } PCI_DEVICE; -typedef struct _PCI_CONFIG_SPACE_ -{ - ushort vendorID; - ushort deviceID; - ushort command; - ushort status; - uchar revision; - uchar classCode[3]; - uchar cacheSize; - uchar latencyTimer; - uchar headerType; - uchar bist; - ADV_PADDR baseAddress[6]; - ushort reserved[4]; - ADV_PADDR optionRomAddr; - ushort reserved2[4]; - uchar irqLine; - uchar irqPin; - uchar minGnt; - uchar maxLatency; +typedef struct _PCI_CONFIG_SPACE_ { + ushort vendorID; + ushort deviceID; + ushort command; + ushort status; + uchar revision; + uchar classCode[3]; + uchar cacheSize; + uchar latencyTimer; + uchar headerType; + uchar bist; + ADV_PADDR baseAddress[6]; + ushort reserved[4]; + ADV_PADDR optionRomAddr; + ushort reserved2[4]; + uchar irqLine; + uchar irqPin; + uchar minGnt; + uchar maxLatency; } PCI_CONFIG_SPACE; - /* * --- Driver Data */ @@ -3949,44 +3913,42 @@ typedef struct _PCI_CONFIG_SPACE_ /* Note: All driver global data should be initialized. */ /* Number of boards detected in system. */ -STATIC int asc_board_count = 0; -STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { NULL }; +static int asc_board_count = 0; +static struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { NULL }; /* Overrun buffer used by all narrow boards. */ -STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; +static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; /* * Global structures required to issue a command. */ -STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } }; -STATIC ASC_SG_HEAD asc_sg_head = { 0 }; +static ASC_SCSI_Q asc_scsi_q = { {0} }; +static ASC_SG_HEAD asc_sg_head = { 0 }; /* List of supported bus types. */ -STATIC ushort asc_bus[ASC_NUM_BUS] __initdata = { - ASC_IS_ISA, - ASC_IS_VL, - ASC_IS_EISA, - ASC_IS_PCI, +static ushort asc_bus[ASC_NUM_BUS] __initdata = { + ASC_IS_ISA, + ASC_IS_VL, + ASC_IS_EISA, + ASC_IS_PCI, }; -STATIC int asc_iopflag = ASC_FALSE; -STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 }; +static int asc_iopflag = ASC_FALSE; +static int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 }; #ifdef ADVANSYS_DEBUG -STATIC char * -asc_bus_name[ASC_NUM_BUS] = { - "ASC_IS_ISA", - "ASC_IS_VL", - "ASC_IS_EISA", - "ASC_IS_PCI", +static char *asc_bus_name[ASC_NUM_BUS] = { + "ASC_IS_ISA", + "ASC_IS_VL", + "ASC_IS_EISA", + "ASC_IS_PCI", }; -STATIC int asc_dbglvl = 3; +static int asc_dbglvl = 3; #endif /* ADVANSYS_DEBUG */ /* Declaration for Asc Library internal data referenced by driver. */ -STATIC PortAddr _asc_def_iop_base[]; - +static PortAddr _asc_def_iop_base[]; /* * --- Driver Function Prototypes @@ -3994,62 +3956,61 @@ STATIC PortAddr _asc_def_iop_base[]; * advansys.h contains function prototypes for functions global to Linux. */ -STATIC irqreturn_t advansys_interrupt(int, void *); -STATIC int advansys_slave_configure(struct scsi_device *); -STATIC void asc_scsi_done_list(struct scsi_cmnd *); -STATIC int asc_execute_scsi_cmnd(struct scsi_cmnd *); -STATIC int asc_build_req(asc_board_t *, struct scsi_cmnd *); -STATIC int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **); -STATIC int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int); -STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); -STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -STATIC void adv_async_callback(ADV_DVC_VAR *, uchar); -STATIC void asc_enqueue(asc_queue_t *, REQP, int); -STATIC REQP asc_dequeue(asc_queue_t *, int); -STATIC REQP asc_dequeue_list(asc_queue_t *, REQP *, int); -STATIC int asc_rmqueue(asc_queue_t *, REQP); -STATIC void asc_execute_queue(asc_queue_t *); +static irqreturn_t advansys_interrupt(int, void *); +static int advansys_slave_configure(struct scsi_device *); +static void asc_scsi_done_list(struct scsi_cmnd *); +static int asc_execute_scsi_cmnd(struct scsi_cmnd *); +static int asc_build_req(asc_board_t *, struct scsi_cmnd *); +static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **); +static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int); +static void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); +static void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); +static void adv_async_callback(ADV_DVC_VAR *, uchar); +static void asc_enqueue(asc_queue_t *, REQP, int); +static REQP asc_dequeue(asc_queue_t *, int); +static REQP asc_dequeue_list(asc_queue_t *, REQP *, int); +static int asc_rmqueue(asc_queue_t *, REQP); +static void asc_execute_queue(asc_queue_t *); #ifdef CONFIG_PROC_FS -STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int); -STATIC int asc_prt_board_devices(struct Scsi_Host *, char *, int); -STATIC int asc_prt_adv_bios(struct Scsi_Host *, char *, int); -STATIC int asc_get_eeprom_string(ushort *serialnum, uchar *cp); -STATIC int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int); -STATIC int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int); -STATIC int asc_prt_driver_conf(struct Scsi_Host *, char *, int); -STATIC int asc_prt_asc_board_info(struct Scsi_Host *, char *, int); -STATIC int asc_prt_adv_board_info(struct Scsi_Host *, char *, int); -STATIC int asc_prt_line(char *, int, char *fmt, ...); +static int asc_proc_copy(off_t, off_t, char *, int, char *, int); +static int asc_prt_board_devices(struct Scsi_Host *, char *, int); +static int asc_prt_adv_bios(struct Scsi_Host *, char *, int); +static int asc_get_eeprom_string(ushort *serialnum, uchar *cp); +static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int); +static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int); +static int asc_prt_driver_conf(struct Scsi_Host *, char *, int); +static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int); +static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int); +static int asc_prt_line(char *, int, char *fmt, ...); #endif /* CONFIG_PROC_FS */ /* Declaration for Asc Library internal functions referenced by driver. */ -STATIC int AscFindSignature(PortAddr); -STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); +static int AscFindSignature(PortAddr); +static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); /* Statistics function prototypes. */ #ifdef ADVANSYS_STATS #ifdef CONFIG_PROC_FS -STATIC int asc_prt_board_stats(struct Scsi_Host *, char *, int); -STATIC int asc_prt_target_stats(struct Scsi_Host *, int, char *, int); +static int asc_prt_board_stats(struct Scsi_Host *, char *, int); +static int asc_prt_target_stats(struct Scsi_Host *, int, char *, int); #endif /* CONFIG_PROC_FS */ #endif /* ADVANSYS_STATS */ /* Debug function prototypes. */ #ifdef ADVANSYS_DEBUG -STATIC void asc_prt_scsi_host(struct Scsi_Host *); -STATIC void asc_prt_scsi_cmnd(struct scsi_cmnd *); -STATIC void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *); -STATIC void asc_prt_asc_dvc_var(ASC_DVC_VAR *); -STATIC void asc_prt_asc_scsi_q(ASC_SCSI_Q *); -STATIC void asc_prt_asc_qdone_info(ASC_QDONE_INFO *); -STATIC void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *); -STATIC void asc_prt_adv_dvc_var(ADV_DVC_VAR *); -STATIC void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *); -STATIC void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *); -STATIC void asc_prt_hex(char *f, uchar *, int); +static void asc_prt_scsi_host(struct Scsi_Host *); +static void asc_prt_scsi_cmnd(struct scsi_cmnd *); +static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *); +static void asc_prt_asc_dvc_var(ASC_DVC_VAR *); +static void asc_prt_asc_scsi_q(ASC_SCSI_Q *); +static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *); +static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *); +static void asc_prt_adv_dvc_var(ADV_DVC_VAR *); +static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *); +static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *); +static void asc_prt_hex(char *f, uchar *, int); #endif /* ADVANSYS_DEBUG */ - #ifdef CONFIG_PROC_FS /* * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] @@ -4073,1389 +4034,210 @@ STATIC void asc_prt_hex(char *f, uchar *, int); */ static int advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, - off_t offset, int length, int inout) + off_t offset, int length, int inout) { - struct Scsi_Host *shp; - asc_board_t *boardp; - int i; - char *cp; - int cplen; - int cnt; - int totcnt; - int leftlen; - char *curbuf; - off_t advoffset; + struct Scsi_Host *shp; + asc_board_t *boardp; + int i; + char *cp; + int cplen; + int cnt; + int totcnt; + int leftlen; + char *curbuf; + off_t advoffset; #ifdef ADVANSYS_STATS - int tgt_id; + int tgt_id; #endif /* ADVANSYS_STATS */ - ASC_DBG(1, "advansys_proc_info: begin\n"); - - /* - * User write not supported. - */ - if (inout == TRUE) { - return(-ENOSYS); - } + ASC_DBG(1, "advansys_proc_info: begin\n"); - /* - * User read of /proc/scsi/advansys/[0...] file. - */ - - /* Find the specified board. */ - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i]->host_no == shost->host_no) { - break; - } - } - if (i == asc_board_count) { - return(-ENOENT); - } - - shp = asc_host[i]; - boardp = ASC_BOARDP(shp); - - /* Copy read data starting at the beginning of the buffer. */ - *start = buffer; - curbuf = buffer; - advoffset = 0; - totcnt = 0; - leftlen = length; - - /* - * Get board configuration information. - * - * advansys_info() returns the board string from its own static buffer. - */ - cp = (char *) advansys_info(shp); - strcat(cp, "\n"); - cplen = strlen(cp); - /* Copy board information. */ - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + /* + * User write not supported. + */ + if (inout == TRUE) { + return (-ENOSYS); + } - /* - * Display Wide Board BIOS Information. - */ - if (ASC_WIDE_BOARD(boardp)) { - cp = boardp->prtbuf; - cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - } + /* + * User read of /proc/scsi/advansys/[0...] file. + */ - /* - * Display driver information for each device attached to the board. - */ - cp = boardp->prtbuf; - cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + /* Find the specified board. */ + for (i = 0; i < asc_board_count; i++) { + if (asc_host[i]->host_no == shost->host_no) { + break; + } + } + if (i == asc_board_count) { + return (-ENOENT); + } - /* - * Display EEPROM configuration for the board. - */ - cp = boardp->prtbuf; - if (ASC_NARROW_BOARD(boardp)) { - cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); - } else { - cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); - } - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + shp = asc_host[i]; + boardp = ASC_BOARDP(shp); + + /* Copy read data starting at the beginning of the buffer. */ + *start = buffer; + curbuf = buffer; + advoffset = 0; + totcnt = 0; + leftlen = length; + + /* + * Get board configuration information. + * + * advansys_info() returns the board string from its own static buffer. + */ + cp = (char *)advansys_info(shp); + strcat(cp, "\n"); + cplen = strlen(cp); + /* Copy board information. */ + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display Wide Board BIOS Information. + */ + if (ASC_WIDE_BOARD(boardp)) { + cp = boardp->prtbuf; + cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = + asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, + cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + } - /* - * Display driver configuration and information for the board. - */ - cp = boardp->prtbuf; - cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + /* + * Display driver information for each device attached to the board. + */ + cp = boardp->prtbuf; + cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display EEPROM configuration for the board. + */ + cp = boardp->prtbuf; + if (ASC_NARROW_BOARD(boardp)) { + cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); + } else { + cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); + } + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display driver configuration and information for the board. + */ + cp = boardp->prtbuf; + cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; #ifdef ADVANSYS_STATS - /* - * Display driver statistics for the board. - */ - cp = boardp->prtbuf; - cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - - /* - * Display driver statistics for each target. - */ - for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) { - cp = boardp->prtbuf; - cplen = asc_prt_target_stats(shp, tgt_id, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - } + /* + * Display driver statistics for the board. + */ + cp = boardp->prtbuf; + cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display driver statistics for each target. + */ + for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) { + cp = boardp->prtbuf; + cplen = asc_prt_target_stats(shp, tgt_id, cp, ASC_PRTBUF_SIZE); + ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); + cnt = + asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, + cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + } #endif /* ADVANSYS_STATS */ - /* - * Display Asc Library dynamic configuration information - * for the board. - */ - cp = boardp->prtbuf; - if (ASC_NARROW_BOARD(boardp)) { - cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE); - } else { - cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE); - } - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - - return totcnt; -} -#endif /* CONFIG_PROC_FS */ - -/* - * advansys_detect() - * - * Detect function for AdvanSys adapters. - * - * Argument is a pointer to the host driver's scsi_hosts entry. - * - * Return number of adapters found. - * - * Note: Because this function is called during system initialization - * it must not call SCSI mid-level functions including scsi_malloc() - * and scsi_free(). - */ -static int __init -advansys_detect(struct scsi_host_template *tpnt) -{ - static int detect_called = ASC_FALSE; - int iop; - int bus; - struct Scsi_Host *shp = NULL; - asc_board_t *boardp = NULL; - ASC_DVC_VAR *asc_dvc_varp = NULL; - ADV_DVC_VAR *adv_dvc_varp = NULL; - adv_sgblk_t *sgp = NULL; - int ioport = 0; - int share_irq = FALSE; - int iolen = 0; - struct device *dev = NULL; -#ifdef CONFIG_PCI - int pci_init_search = 0; - struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED]; - int pci_card_cnt_max = 0; - int pci_card_cnt = 0; - struct pci_dev *pci_devp = NULL; - int pci_device_id_cnt = 0; - unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { - PCI_DEVICE_ID_ASP_1200A, - PCI_DEVICE_ID_ASP_ABP940, - PCI_DEVICE_ID_ASP_ABP940U, - PCI_DEVICE_ID_ASP_ABP940UW, - PCI_DEVICE_ID_38C0800_REV1, - PCI_DEVICE_ID_38C1600_REV1 - }; - ADV_PADDR pci_memory_address; -#endif /* CONFIG_PCI */ - int warn_code, err_code; - int ret; - - if (detect_called == ASC_FALSE) { - detect_called = ASC_TRUE; - } else { - printk("AdvanSys SCSI: advansys_detect() multiple calls ignored\n"); - return 0; - } - - ASC_DBG(1, "advansys_detect: begin\n"); - - asc_board_count = 0; - - /* - * If I/O port probing has been modified, then verify and - * clean-up the 'asc_ioport' list. - */ - if (asc_iopflag == ASC_TRUE) { - for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) { - ASC_DBG2(1, "advansys_detect: asc_ioport[%d] 0x%x\n", - ioport, asc_ioport[ioport]); - if (asc_ioport[ioport] != 0) { - for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) { - if (_asc_def_iop_base[iop] == asc_ioport[ioport]) { - break; - } - } - if (iop == ASC_IOADR_TABLE_MAX_IX) { - printk( -"AdvanSys SCSI: specified I/O Port 0x%X is invalid\n", - asc_ioport[ioport]); - asc_ioport[ioport] = 0; - } - } - } - ioport = 0; - } - - for (bus = 0; bus < ASC_NUM_BUS; bus++) { - - ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n", - bus, asc_bus_name[bus]); - iop = 0; - - while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) { - - ASC_DBG1(2, "advansys_detect: asc_board_count %d\n", - asc_board_count); - - switch (asc_bus[bus]) { - case ASC_IS_ISA: - case ASC_IS_VL: -#ifdef CONFIG_ISA - if (asc_iopflag == ASC_FALSE) { - iop = AscSearchIOPortAddr(iop, asc_bus[bus]); - } else { - /* - * ISA and VL I/O port scanning has either been - * eliminated or limited to selected ports on - * the LILO command line, /etc/lilo.conf, or - * by setting variables when the module was loaded. - */ - ASC_DBG(1, "advansys_detect: I/O port scanning modified\n"); - ioport_try_again: - iop = 0; - for (; ioport < ASC_NUM_IOPORT_PROBE; ioport++) { - if ((iop = asc_ioport[ioport]) != 0) { - break; - } - } - if (iop) { - ASC_DBG1(1, - "advansys_detect: probing I/O port 0x%x...\n", - iop); - 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. */ - asc_ioport[ioport] = 0; - goto ioport_try_again; - } else if (AscFindSignature(iop) == ASC_FALSE) { - 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 { - /* - * If this isn't an ISA board, then it must be - * a VL board. If currently looking an ISA - * board is being looked for then try for - * another ISA board in 'asc_ioport'. - */ - if (asc_bus[bus] == ASC_IS_ISA && - (AscGetChipVersion(iop, ASC_IS_ISA) & - ASC_CHIP_VER_ISA_BIT) == 0) { - /* - * Don't clear 'asc_ioport[ioport]'. Try - * this board again for VL. Increment - * 'ioport' past this board. - */ - ioport++; - release_region(iop, ASC_IOADR_GAP); - goto ioport_try_again; - } - } - /* - * This board appears good, don't try the I/O port - * again by clearing its value. Increment 'ioport' - * for the next iteration. - */ - asc_ioport[ioport++] = 0; - } - } -#endif /* CONFIG_ISA */ - break; - - case ASC_IS_EISA: -#ifdef CONFIG_ISA - iop = AscSearchIOPortAddr(iop, asc_bus[bus]); -#endif /* CONFIG_ISA */ - break; - - case ASC_IS_PCI: -#ifdef CONFIG_PCI - if (pci_init_search == 0) { - int i, j; - - pci_init_search = 1; - - /* Find all PCI cards. */ - while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) { - if ((pci_devp = pci_find_device(PCI_VENDOR_ID_ASP, - pci_device_id[pci_device_id_cnt], pci_devp)) == - NULL) { - pci_device_id_cnt++; - } else { - if (pci_enable_device(pci_devp) == 0) { - pci_devicep[pci_card_cnt_max++] = pci_devp; - } - } - } - - /* - * Sort PCI cards in ascending order by PCI Bus, Slot, - * and Device Number. - */ - for (i = 0; i < pci_card_cnt_max - 1; i++) - { - for (j = i + 1; j < pci_card_cnt_max; j++) { - if ((pci_devicep[j]->bus->number < - pci_devicep[i]->bus->number) || - ((pci_devicep[j]->bus->number == - pci_devicep[i]->bus->number) && - (pci_devicep[j]->devfn < - pci_devicep[i]->devfn))) { - pci_devp = pci_devicep[i]; - pci_devicep[i] = pci_devicep[j]; - pci_devicep[j] = pci_devp; - } - } - } - - pci_card_cnt = 0; - } else { - pci_card_cnt++; - } - - if (pci_card_cnt == pci_card_cnt_max) { - iop = 0; - } else { - pci_devp = pci_devicep[pci_card_cnt]; - - ASC_DBG2(2, - "advansys_detect: devfn %d, bus number %d\n", - pci_devp->devfn, pci_devp->bus->number); - iop = pci_resource_start(pci_devp, 0); - ASC_DBG2(1, - "advansys_detect: vendorID %X, deviceID %X\n", - pci_devp->vendor, pci_devp->device); - ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n", - iop, pci_devp->irq); - } - if(pci_devp) - dev = &pci_devp->dev; - -#endif /* CONFIG_PCI */ - break; - - default: - ASC_PRINT1("advansys_detect: unknown bus type: %d\n", - asc_bus[bus]); - break; - } - ASC_DBG1(1, "advansys_detect: iop 0x%x\n", iop); - - /* - * Adapter not found, try next bus type. - */ - if (iop == 0) { - break; - } - - /* - * Adapter found. - * - * Register the adapter, get its configuration, and - * initialize it. - */ - ASC_DBG(2, "advansys_detect: scsi_register()\n"); - shp = scsi_register(tpnt, sizeof(asc_board_t)); - - if (shp == NULL) { - continue; - } - - /* Save a pointer to the Scsi_Host of each board found. */ - asc_host[asc_board_count++] = shp; - - /* Initialize private per board data */ - boardp = ASC_BOARDP(shp); - memset(boardp, 0, sizeof(asc_board_t)); - boardp->id = asc_board_count - 1; - - /* Initialize spinlock. */ - spin_lock_init(&boardp->lock); - - /* - * Handle both narrow and wide boards. - * - * If a Wide board was detected, set the board structure - * wide board flag. Set-up the board structure based on - * the board type. - */ -#ifdef CONFIG_PCI - if (asc_bus[bus] == ASC_IS_PCI && - (pci_devp->device == PCI_DEVICE_ID_ASP_ABP940UW || - pci_devp->device == PCI_DEVICE_ID_38C0800_REV1 || - pci_devp->device == PCI_DEVICE_ID_38C1600_REV1)) - { - boardp->flags |= ASC_IS_WIDE_BOARD; - } -#endif /* CONFIG_PCI */ - - if (ASC_NARROW_BOARD(boardp)) { - ASC_DBG(1, "advansys_detect: narrow board\n"); - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - asc_dvc_varp->bus_type = asc_bus[bus]; - asc_dvc_varp->drv_ptr = boardp; - asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg; - asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0]; - asc_dvc_varp->iop_base = iop; - asc_dvc_varp->isr_callback = asc_isr_callback; - } else { - ASC_DBG(1, "advansys_detect: wide board\n"); - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - adv_dvc_varp->drv_ptr = boardp; - adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg; - adv_dvc_varp->isr_callback = adv_isr_callback; - adv_dvc_varp->async_callback = adv_async_callback; -#ifdef CONFIG_PCI - if (pci_devp->device == PCI_DEVICE_ID_ASP_ABP940UW) - { - ASC_DBG(1, "advansys_detect: ASC-3550\n"); - adv_dvc_varp->chip_type = ADV_CHIP_ASC3550; - } else if (pci_devp->device == PCI_DEVICE_ID_38C0800_REV1) - { - ASC_DBG(1, "advansys_detect: ASC-38C0800\n"); - adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800; - } else - { - ASC_DBG(1, "advansys_detect: ASC-38C1600\n"); - adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600; - } -#endif /* CONFIG_PCI */ - - /* - * Map the board's registers into virtual memory for - * PCI slave access. Only memory accesses are used to - * access the board's registers. - * - * Note: The PCI register base address is not always - * page aligned, but the address passed to ioremap() - * must be page aligned. It is guaranteed that the - * PCI register base address will not cross a page - * boundary. - */ - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - iolen = ADV_3550_IOLEN; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - iolen = ADV_38C0800_IOLEN; - } else - { - iolen = ADV_38C1600_IOLEN; - } -#ifdef CONFIG_PCI - pci_memory_address = pci_resource_start(pci_devp, 1); - ASC_DBG1(1, "advansys_detect: pci_memory_address: 0x%lx\n", - (ulong) pci_memory_address); - if ((boardp->ioremap_addr = - ioremap(pci_memory_address & PAGE_MASK, - PAGE_SIZE)) == 0) { - ASC_PRINT3( -"advansys_detect: board %d: ioremap(%x, %d) returned NULL\n", - boardp->id, pci_memory_address, iolen); - scsi_unregister(shp); - asc_board_count--; - continue; - } - ASC_DBG1(1, "advansys_detect: ioremap_addr: 0x%lx\n", - (ulong) boardp->ioremap_addr); - adv_dvc_varp->iop_base = (AdvPortAddr) - (boardp->ioremap_addr + - (pci_memory_address - (pci_memory_address & PAGE_MASK))); - ASC_DBG1(1, "advansys_detect: iop_base: 0x%lx\n", - adv_dvc_varp->iop_base); -#endif /* CONFIG_PCI */ - - /* - * Even though it isn't used to access wide boards, other - * than for the debug line below, save I/O Port address so - * that it can be reported. - */ - boardp->ioport = iop; - - ASC_DBG2(1, -"advansys_detect: iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n", - (ushort) inp(iop + 1), (ushort) inpw(iop)); - } - -#ifdef CONFIG_PROC_FS - /* - * Allocate buffer for printing information from - * /proc/scsi/advansys/[0...]. - */ - if ((boardp->prtbuf = - kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) { - ASC_PRINT3( -"advansys_detect: board %d: kmalloc(%d, %d) returned NULL\n", - boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC); - scsi_unregister(shp); - asc_board_count--; - continue; - } -#endif /* CONFIG_PROC_FS */ - - if (ASC_NARROW_BOARD(boardp)) { - asc_dvc_varp->cfg->dev = dev; - /* - * Set the board bus type and PCI IRQ before - * calling AscInitGetConfig(). - */ - switch (asc_dvc_varp->bus_type) { -#ifdef CONFIG_ISA - case ASC_IS_ISA: - shp->unchecked_isa_dma = TRUE; - share_irq = FALSE; - break; - case ASC_IS_VL: - shp->unchecked_isa_dma = FALSE; - share_irq = FALSE; - break; - case ASC_IS_EISA: - shp->unchecked_isa_dma = FALSE; - share_irq = TRUE; - break; -#endif /* CONFIG_ISA */ -#ifdef CONFIG_PCI - case ASC_IS_PCI: - shp->irq = asc_dvc_varp->irq_no = pci_devp->irq; - asc_dvc_varp->cfg->pci_slot_info = - ASC_PCI_MKID(pci_devp->bus->number, - PCI_SLOT(pci_devp->devfn), - PCI_FUNC(pci_devp->devfn)); - shp->unchecked_isa_dma = FALSE; - share_irq = TRUE; - break; -#endif /* CONFIG_PCI */ - default: - ASC_PRINT2( -"advansys_detect: board %d: unknown adapter type: %d\n", - boardp->id, asc_dvc_varp->bus_type); - shp->unchecked_isa_dma = TRUE; - share_irq = FALSE; - break; - } - } else { - adv_dvc_varp->cfg->dev = dev; - /* - * For Wide boards set PCI information before calling - * AdvInitGetConfig(). - */ -#ifdef CONFIG_PCI - shp->irq = adv_dvc_varp->irq_no = pci_devp->irq; - adv_dvc_varp->cfg->pci_slot_info = - ASC_PCI_MKID(pci_devp->bus->number, - PCI_SLOT(pci_devp->devfn), - PCI_FUNC(pci_devp->devfn)); - shp->unchecked_isa_dma = FALSE; - share_irq = TRUE; -#endif /* CONFIG_PCI */ - } - - /* - * Read the board configuration. - */ - if (ASC_NARROW_BOARD(boardp)) { - /* - * NOTE: AscInitGetConfig() may change the board's - * bus_type value. The asc_bus[bus] value should no - * longer be used. If the bus_type field must be - * referenced only use the bit-wise AND operator "&". - */ - ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n"); - switch(ret = AscInitGetConfig(asc_dvc_varp)) { - case 0: /* No error */ - break; - case ASC_WARN_IO_PORT_ROTATE: - ASC_PRINT1( -"AscInitGetConfig: board %d: I/O port address modified\n", - boardp->id); - break; - case ASC_WARN_AUTO_CONFIG: - ASC_PRINT1( -"AscInitGetConfig: board %d: I/O port increment switch enabled\n", - boardp->id); - break; - case ASC_WARN_EEPROM_CHKSUM: - ASC_PRINT1( -"AscInitGetConfig: board %d: EEPROM checksum error\n", - boardp->id); - break; - case ASC_WARN_IRQ_MODIFIED: - ASC_PRINT1( -"AscInitGetConfig: board %d: IRQ modified\n", - boardp->id); - break; - case ASC_WARN_CMD_QNG_CONFLICT: - ASC_PRINT1( -"AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n", - boardp->id); - break; - default: - ASC_PRINT2( -"AscInitGetConfig: board %d: unknown warning: 0x%x\n", - boardp->id, ret); - break; - } - if ((err_code = asc_dvc_varp->err_code) != 0) { - ASC_PRINT3( -"AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", - boardp->id, asc_dvc_varp->init_state, - asc_dvc_varp->err_code); - } - } else { - ASC_DBG(2, "advansys_detect: AdvInitGetConfig()\n"); - if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) { - ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n", - boardp->id, ret); - } - if ((err_code = adv_dvc_varp->err_code) != 0) { - ASC_PRINT2( -"AdvInitGetConfig: board %d error: err_code 0x%x\n", - boardp->id, adv_dvc_varp->err_code); - } - } - - if (err_code != 0) { -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* - * Save the EEPROM configuration so that it can be displayed - * from /proc/scsi/advansys/[0...]. - */ - if (ASC_NARROW_BOARD(boardp)) { - - ASCEEP_CONFIG *ep; - - /* - * Set the adapter's target id bit in the 'init_tidmask' field. - */ - boardp->init_tidmask |= - ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id); - - /* - * Save EEPROM settings for the board. - */ - ep = &boardp->eep_config.asc_eep; - - ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable; - ep->disc_enable = asc_dvc_varp->cfg->disc_enable; - ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled; - ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed); - ep->start_motor = asc_dvc_varp->start_motor; - ep->cntl = asc_dvc_varp->dvc_cntl; - ep->no_scam = asc_dvc_varp->no_scam; - ep->max_total_qng = asc_dvc_varp->max_total_qng; - ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id); - /* 'max_tag_qng' is set to the same value for every device. */ - ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0]; - ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0]; - ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1]; - ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2]; - ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3]; - ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4]; - ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5]; - - /* - * Modify board configuration. - */ - ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n"); - switch (ret = AscInitSetConfig(asc_dvc_varp)) { - case 0: /* No error. */ - break; - case ASC_WARN_IO_PORT_ROTATE: - ASC_PRINT1( -"AscInitSetConfig: board %d: I/O port address modified\n", - boardp->id); - break; - case ASC_WARN_AUTO_CONFIG: - ASC_PRINT1( -"AscInitSetConfig: board %d: I/O port increment switch enabled\n", - boardp->id); - break; - case ASC_WARN_EEPROM_CHKSUM: - ASC_PRINT1( -"AscInitSetConfig: board %d: EEPROM checksum error\n", - boardp->id); - break; - case ASC_WARN_IRQ_MODIFIED: - ASC_PRINT1( -"AscInitSetConfig: board %d: IRQ modified\n", - boardp->id); - break; - case ASC_WARN_CMD_QNG_CONFLICT: - ASC_PRINT1( -"AscInitSetConfig: board %d: tag queuing w/o disconnects\n", - boardp->id); - break; - default: - ASC_PRINT2( -"AscInitSetConfig: board %d: unknown warning: 0x%x\n", - boardp->id, ret); - break; - } - if (asc_dvc_varp->err_code != 0) { - ASC_PRINT3( -"AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", - boardp->id, asc_dvc_varp->init_state, - asc_dvc_varp->err_code); -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* - * Finish initializing the 'Scsi_Host' structure. - */ - /* AscInitSetConfig() will set the IRQ for non-PCI boards. */ - if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) { - shp->irq = asc_dvc_varp->irq_no; - } - } else { - ADVEEP_3550_CONFIG *ep_3550; - ADVEEP_38C0800_CONFIG *ep_38C0800; - ADVEEP_38C1600_CONFIG *ep_38C1600; - - /* - * Save Wide EEP Configuration Information. - */ - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - ep_3550 = &boardp->eep_config.adv_3550_eep; - - ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id; - ep_3550->max_host_qng = adv_dvc_varp->max_host_qng; - ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng; - ep_3550->termination = adv_dvc_varp->cfg->termination; - ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable; - ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl; - ep_3550->wdtr_able = adv_dvc_varp->wdtr_able; - ep_3550->sdtr_able = adv_dvc_varp->sdtr_able; - ep_3550->ultra_able = adv_dvc_varp->ultra_able; - ep_3550->tagqng_able = adv_dvc_varp->tagqng_able; - ep_3550->start_motor = adv_dvc_varp->start_motor; - ep_3550->scsi_reset_delay = adv_dvc_varp->scsi_reset_wait; - ep_3550->serial_number_word1 = - adv_dvc_varp->cfg->serial1; - ep_3550->serial_number_word2 = - adv_dvc_varp->cfg->serial2; - ep_3550->serial_number_word3 = - adv_dvc_varp->cfg->serial3; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; - - ep_38C0800->adapter_scsi_id = adv_dvc_varp->chip_scsi_id; - ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng; - ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng; - ep_38C0800->termination_lvd = - adv_dvc_varp->cfg->termination; - ep_38C0800->disc_enable = adv_dvc_varp->cfg->disc_enable; - ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl; - ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able; - ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able; - ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1; - ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2; - ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3; - ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4; - ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able; - ep_38C0800->start_motor = adv_dvc_varp->start_motor; - ep_38C0800->scsi_reset_delay = - adv_dvc_varp->scsi_reset_wait; - ep_38C0800->serial_number_word1 = - adv_dvc_varp->cfg->serial1; - ep_38C0800->serial_number_word2 = - adv_dvc_varp->cfg->serial2; - ep_38C0800->serial_number_word3 = - adv_dvc_varp->cfg->serial3; - } else - { - ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; - - ep_38C1600->adapter_scsi_id = adv_dvc_varp->chip_scsi_id; - ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng; - ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng; - ep_38C1600->termination_lvd = - adv_dvc_varp->cfg->termination; - ep_38C1600->disc_enable = adv_dvc_varp->cfg->disc_enable; - ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl; - ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able; - ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able; - ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1; - ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2; - ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3; - ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4; - ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able; - ep_38C1600->start_motor = adv_dvc_varp->start_motor; - ep_38C1600->scsi_reset_delay = - adv_dvc_varp->scsi_reset_wait; - ep_38C1600->serial_number_word1 = - adv_dvc_varp->cfg->serial1; - ep_38C1600->serial_number_word2 = - adv_dvc_varp->cfg->serial2; - ep_38C1600->serial_number_word3 = - adv_dvc_varp->cfg->serial3; - } - - /* - * Set the adapter's target id bit in the 'init_tidmask' field. - */ - boardp->init_tidmask |= - ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id); - - /* - * Finish initializing the 'Scsi_Host' structure. - */ - shp->irq = adv_dvc_varp->irq_no; - } - - /* - * Channels are numbered beginning with 0. For AdvanSys one host - * structure supports one channel. Multi-channel boards have a - * separate host structure for each channel. - */ - shp->max_channel = 0; - if (ASC_NARROW_BOARD(boardp)) { - shp->max_id = ASC_MAX_TID + 1; - shp->max_lun = ASC_MAX_LUN + 1; - - shp->io_port = asc_dvc_varp->iop_base; - boardp->asc_n_io_port = ASC_IOADR_GAP; - shp->this_id = asc_dvc_varp->cfg->chip_scsi_id; - - /* Set maximum number of queues the adapter can handle. */ - shp->can_queue = asc_dvc_varp->max_total_qng; - } else { - shp->max_id = ADV_MAX_TID + 1; - shp->max_lun = ADV_MAX_LUN + 1; - - /* - * Save the I/O Port address and length even though - * I/O ports are not used to access Wide boards. - * Instead the Wide boards are accessed with - * PCI Memory Mapped I/O. - */ - shp->io_port = iop; - boardp->asc_n_io_port = iolen; - - shp->this_id = adv_dvc_varp->chip_scsi_id; - - /* Set maximum number of queues the adapter can handle. */ - shp->can_queue = adv_dvc_varp->max_host_qng; - } - - /* - * 'n_io_port' currently is one byte. - * - * Set a value to 'n_io_port', but never referenced it because - * it may be truncated. - */ - shp->n_io_port = boardp->asc_n_io_port <= 255 ? - boardp->asc_n_io_port : 255; - - /* - * Following v1.3.89, 'cmd_per_lun' is no longer needed - * and should be set to zero. - * - * But because of a bug introduced in v1.3.89 if the driver is - * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level - * SCSI function 'allocate_device' will panic. To allow the driver - * to work as a module in these kernels set 'cmd_per_lun' to 1. - * - * Note: This is wrong. cmd_per_lun should be set to the depth - * you want on untagged devices always. -#ifdef MODULE - */ - shp->cmd_per_lun = 1; -/* #else - shp->cmd_per_lun = 0; -#endif */ - - /* - * Set the maximum number of scatter-gather elements the - * adapter can handle. - */ - if (ASC_NARROW_BOARD(boardp)) { - /* - * Allow two commands with 'sg_tablesize' scatter-gather - * elements to be executed simultaneously. This value is - * the theoretical hardware limit. It may be decreased - * below. - */ - shp->sg_tablesize = - (((asc_dvc_varp->max_total_qng - 2) / 2) * - ASC_SG_LIST_PER_Q) + 1; - } else { - shp->sg_tablesize = ADV_MAX_SG_LIST; - } - - /* - * The value of 'sg_tablesize' can not exceed the SCSI - * mid-level driver definition of SG_ALL. SG_ALL also - * must not be exceeded, because it is used to define the - * size of the scatter-gather table in 'struct asc_sg_head'. - */ - if (shp->sg_tablesize > SG_ALL) { - shp->sg_tablesize = SG_ALL; - } - - ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n", - shp->sg_tablesize); - - /* BIOS start address. */ - if (ASC_NARROW_BOARD(boardp)) { - shp->base = - ((ulong) AscGetChipBiosAddress( - asc_dvc_varp->iop_base, - asc_dvc_varp->bus_type)); - } else { - /* - * Fill-in BIOS board variables. The Wide BIOS saves - * information in LRAM that is used by the driver. - */ - AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_SIGNATURE, - boardp->bios_signature); - AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_VERSION, - boardp->bios_version); - AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODESEG, - boardp->bios_codeseg); - AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN, - boardp->bios_codelen); - - ASC_DBG2(1, - "advansys_detect: bios_signature 0x%x, bios_version 0x%x\n", - boardp->bios_signature, boardp->bios_version); - - ASC_DBG2(1, - "advansys_detect: bios_codeseg 0x%x, bios_codelen 0x%x\n", - boardp->bios_codeseg, boardp->bios_codelen); - - /* - * If the BIOS saved a valid signature, then fill in - * the BIOS code segment base address. - */ - if (boardp->bios_signature == 0x55AA) { - /* - * Convert x86 realmode code segment to a linear - * address by shifting left 4. - */ - shp->base = ((ulong) boardp->bios_codeseg << 4); - } else { - shp->base = 0; - } - } - - /* - * Register Board Resources - I/O Port, DMA, IRQ - */ - - /* - * Register I/O port range. - * - * For Wide boards the I/O ports are not used to access - * the board, but request the region anyway. - * - * 'shp->n_io_port' is not referenced, because it may be truncated. - */ - ASC_DBG2(2, - "advansys_detect: request_region port 0x%lx, len 0x%x\n", - (ulong) shp->io_port, boardp->asc_n_io_port); - if (request_region(shp->io_port, boardp->asc_n_io_port, - "advansys") == NULL) { - ASC_PRINT3( -"advansys_detect: board %d: request_region() failed, port 0x%lx, len 0x%x\n", - boardp->id, (ulong) shp->io_port, boardp->asc_n_io_port); -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* Register DMA Channel for Narrow boards. */ - shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ -#ifdef CONFIG_ISA - if (ASC_NARROW_BOARD(boardp)) { - /* Register DMA channel for ISA bus. */ - if (asc_dvc_varp->bus_type & ASC_IS_ISA) { - shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel; - if ((ret = - request_dma(shp->dma_channel, "advansys")) != 0) { - ASC_PRINT3( -"advansys_detect: board %d: request_dma() %d failed %d\n", - boardp->id, shp->dma_channel, ret); - release_region(shp->io_port, boardp->asc_n_io_port); -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - AscEnableIsaDma(shp->dma_channel); - } - } -#endif /* CONFIG_ISA */ + /* + * Display Asc Library dynamic configuration information + * for the board. + */ + cp = boardp->prtbuf; + if (ASC_NARROW_BOARD(boardp)) { + cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE); + } else { + cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE); + } + ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; - /* Register IRQ Number. */ - ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq); - /* - * If request_irq() fails with the IRQF_DISABLED flag set, - * then try again without the IRQF_DISABLED flag set. This - * allows IRQ sharing to work even with other drivers that - * do not set the IRQF_DISABLED flag. - * - * If IRQF_DISABLED is not set, then interrupts are enabled - * before the driver interrupt function is called. - */ - if (((ret = request_irq(shp->irq, advansys_interrupt, - IRQF_DISABLED | (share_irq == TRUE ? IRQF_SHARED : 0), - "advansys", boardp)) != 0) && - ((ret = request_irq(shp->irq, advansys_interrupt, - (share_irq == TRUE ? IRQF_SHARED : 0), - "advansys", boardp)) != 0)) - { - if (ret == -EBUSY) { - ASC_PRINT2( -"advansys_detect: board %d: request_irq(): IRQ 0x%x already in use.\n", - boardp->id, shp->irq); - } else if (ret == -EINVAL) { - ASC_PRINT2( -"advansys_detect: board %d: request_irq(): IRQ 0x%x not valid.\n", - boardp->id, shp->irq); - } else { - ASC_PRINT3( -"advansys_detect: board %d: request_irq(): IRQ 0x%x failed with %d\n", - boardp->id, shp->irq, ret); - } - release_region(shp->io_port, boardp->asc_n_io_port); - iounmap(boardp->ioremap_addr); - if (shp->dma_channel != NO_ISA_DMA) { - free_dma(shp->dma_channel); - } -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - asc_board_count--; - continue; - } - - /* - * Initialize board RISC chip and enable interrupts. - */ - if (ASC_NARROW_BOARD(boardp)) { - ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n"); - warn_code = AscInitAsc1000Driver(asc_dvc_varp); - err_code = asc_dvc_varp->err_code; - - if (warn_code || err_code) { - ASC_PRINT4( -"advansys_detect: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n", - boardp->id, asc_dvc_varp->init_state, - warn_code, err_code); - } - } else { - ADV_CARR_T *carrp; - int req_cnt = 0; - adv_req_t *reqp = NULL; - int sg_cnt = 0; - - /* - * Allocate buffer carrier structures. The total size - * is about 4 KB, so allocate all at once. - */ - carrp = - (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC); - ASC_DBG1(1, "advansys_detect: carrp 0x%lx\n", (ulong) carrp); - - if (carrp == NULL) { - goto kmalloc_error; - } - - /* - * Allocate up to 'max_host_qng' request structures for - * the Wide board. The total size is about 16 KB, so - * allocate all at once. If the allocation fails decrement - * and try again. - */ - for (req_cnt = adv_dvc_varp->max_host_qng; - req_cnt > 0; req_cnt--) { - - reqp = (adv_req_t *) - kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC); - - ASC_DBG3(1, - "advansys_detect: reqp 0x%lx, req_cnt %d, bytes %lu\n", - (ulong) reqp, req_cnt, - (ulong) sizeof(adv_req_t) * req_cnt); - - if (reqp != NULL) { - break; - } - } - if (reqp == NULL) - { - goto kmalloc_error; - } - - /* - * Allocate up to ADV_TOT_SG_BLOCK request structures for - * the Wide board. Each structure is about 136 bytes. - */ - boardp->adv_sgblkp = NULL; - for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) { - - sgp = (adv_sgblk_t *) - kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC); - - if (sgp == NULL) { - break; - } - - sgp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgp; - - } - ASC_DBG3(1, - "advansys_detect: sg_cnt %d * %u = %u bytes\n", - sg_cnt, sizeof(adv_sgblk_t), - (unsigned) (sizeof(adv_sgblk_t) * sg_cnt)); - - /* - * If no request structures or scatter-gather structures could - * be allocated, then return an error. Otherwise continue with - * initialization. - */ - kmalloc_error: - if (carrp == NULL) - { - ASC_PRINT1( -"advansys_detect: board %d error: failed to kmalloc() carrier buffer.\n", - boardp->id); - err_code = ADV_ERROR; - } else if (reqp == NULL) { - kfree(carrp); - ASC_PRINT1( -"advansys_detect: board %d error: failed to kmalloc() adv_req_t buffer.\n", - boardp->id); - err_code = ADV_ERROR; - } else if (boardp->adv_sgblkp == NULL) { - kfree(carrp); - kfree(reqp); - ASC_PRINT1( -"advansys_detect: board %d error: failed to kmalloc() adv_sgblk_t buffers.\n", - boardp->id); - err_code = ADV_ERROR; - } else { - - /* Save carrier buffer pointer. */ - boardp->orig_carrp = carrp; - - /* - * Save original pointer for kfree() in case the - * driver is built as a module and can be unloaded. - */ - boardp->orig_reqp = reqp; - - adv_dvc_varp->carrier_buf = carrp; - - /* - * Point 'adv_reqp' to the request structures and - * link them together. - */ - req_cnt--; - reqp[req_cnt].next_reqp = NULL; - for (; req_cnt > 0; req_cnt--) { - reqp[req_cnt - 1].next_reqp = &reqp[req_cnt]; - } - boardp->adv_reqp = &reqp[0]; - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - ASC_DBG(2, - "advansys_detect: AdvInitAsc3550Driver()\n"); - warn_code = AdvInitAsc3550Driver(adv_dvc_varp); - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - ASC_DBG(2, - "advansys_detect: AdvInitAsc38C0800Driver()\n"); - warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp); - } else { - ASC_DBG(2, - "advansys_detect: AdvInitAsc38C1600Driver()\n"); - warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp); - } - err_code = adv_dvc_varp->err_code; - - if (warn_code || err_code) { - ASC_PRINT3( -"advansys_detect: board %d error: warn 0x%x, error 0x%x\n", - boardp->id, warn_code, err_code); - } - } - } - - if (err_code != 0) { - release_region(shp->io_port, boardp->asc_n_io_port); - if (ASC_WIDE_BOARD(boardp)) { - iounmap(boardp->ioremap_addr); - kfree(boardp->orig_carrp); - boardp->orig_carrp = NULL; - if (boardp->orig_reqp) { - kfree(boardp->orig_reqp); - boardp->orig_reqp = boardp->adv_reqp = NULL; - } - while ((sgp = boardp->adv_sgblkp) != NULL) - { - boardp->adv_sgblkp = sgp->next_sgblkp; - kfree(sgp); - } - } - if (shp->dma_channel != NO_ISA_DMA) { - free_dma(shp->dma_channel); - } -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - free_irq(shp->irq, boardp); - scsi_unregister(shp); - asc_board_count--; - continue; - } - ASC_DBG_PRT_SCSI_HOST(2, shp); - } - } + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count); - return asc_board_count; + return totcnt; } - -/* - * advansys_release() - * - * Release resources allocated for a single AdvanSys adapter. - */ -static int -advansys_release(struct Scsi_Host *shp) -{ - asc_board_t *boardp; - - ASC_DBG(1, "advansys_release: begin\n"); - boardp = ASC_BOARDP(shp); - free_irq(shp->irq, boardp); - if (shp->dma_channel != NO_ISA_DMA) { - ASC_DBG(1, "advansys_release: free_dma()\n"); - free_dma(shp->dma_channel); - } - release_region(shp->io_port, boardp->asc_n_io_port); - if (ASC_WIDE_BOARD(boardp)) { - adv_sgblk_t *sgp = NULL; - - iounmap(boardp->ioremap_addr); - kfree(boardp->orig_carrp); - boardp->orig_carrp = NULL; - if (boardp->orig_reqp) { - kfree(boardp->orig_reqp); - boardp->orig_reqp = boardp->adv_reqp = NULL; - } - while ((sgp = boardp->adv_sgblkp) != NULL) - { - boardp->adv_sgblkp = sgp->next_sgblkp; - kfree(sgp); - } - } -#ifdef CONFIG_PROC_FS - ASC_ASSERT(boardp->prtbuf != NULL); - kfree(boardp->prtbuf); #endif /* CONFIG_PROC_FS */ - scsi_unregister(shp); - ASC_DBG(1, "advansys_release: end\n"); - return 0; -} /* * advansys_info() @@ -5466,91 +4248,87 @@ advansys_release(struct Scsi_Host *shp) * Note: The information line should not exceed ASC_INFO_SIZE bytes, * otherwise the static 'info' array will be overrun. */ -static const char * -advansys_info(struct Scsi_Host *shp) +static const char *advansys_info(struct Scsi_Host *shost) { - static char info[ASC_INFO_SIZE]; - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - ADV_DVC_VAR *adv_dvc_varp; - char *busname; - int iolen; - char *widename = NULL; - - boardp = ASC_BOARDP(shp); - if (ASC_NARROW_BOARD(boardp)) { - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - ASC_DBG(1, "advansys_info: begin\n"); - if (asc_dvc_varp->bus_type & ASC_IS_ISA) { - if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) { - busname = "ISA PnP"; - } else { - busname = "ISA"; - } - /* Don't reference 'shp->n_io_port'; It may be truncated. */ - sprintf(info, -"AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X", - ASC_VERSION, busname, - (ulong) shp->io_port, - (ulong) shp->io_port + boardp->asc_n_io_port - 1, - shp->irq, shp->dma_channel); - } else { - if (asc_dvc_varp->bus_type & ASC_IS_VL) { - busname = "VL"; - } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { - busname = "EISA"; - } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { - if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) - == ASC_IS_PCI_ULTRA) { - busname = "PCI Ultra"; - } else { - busname = "PCI"; - } - } else { - busname = "?"; - ASC_PRINT2( "advansys_info: board %d: unknown bus type %d\n", - boardp->id, asc_dvc_varp->bus_type); - } - /* Don't reference 'shp->n_io_port'; It may be truncated. */ - sprintf(info, - "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X", - ASC_VERSION, busname, - (ulong) shp->io_port, - (ulong) shp->io_port + boardp->asc_n_io_port - 1, - shp->irq); - } - } else { - /* - * Wide Adapter Information - * - * Memory-mapped I/O is used instead of I/O space to access - * the adapter, but display the I/O Port range. The Memory - * I/O address is displayed through the driver /proc file. - */ - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - iolen = ADV_3550_IOLEN; - widename = "Ultra-Wide"; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - iolen = ADV_38C0800_IOLEN; - widename = "Ultra2-Wide"; - } else - { - iolen = ADV_38C1600_IOLEN; - widename = "Ultra3-Wide"; - } - sprintf(info, "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X", - ASC_VERSION, - widename, - (ulong) adv_dvc_varp->iop_base, - (ulong) adv_dvc_varp->iop_base + iolen - 1, - shp->irq); - } - ASC_ASSERT(strlen(info) < ASC_INFO_SIZE); - ASC_DBG(1, "advansys_info: end\n"); - return info; + static char info[ASC_INFO_SIZE]; + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; + ADV_DVC_VAR *adv_dvc_varp; + char *busname; + int iolen; + char *widename = NULL; + + boardp = ASC_BOARDP(shost); + if (ASC_NARROW_BOARD(boardp)) { + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + ASC_DBG(1, "advansys_info: begin\n"); + if (asc_dvc_varp->bus_type & ASC_IS_ISA) { + if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == + ASC_IS_ISAPNP) { + busname = "ISA PnP"; + } else { + busname = "ISA"; + } + /* Don't reference 'shost->n_io_port'; It may be truncated. */ + sprintf(info, + "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X", + ASC_VERSION, busname, + (ulong)shost->io_port, + (ulong)shost->io_port + boardp->asc_n_io_port - + 1, shost->irq, shost->dma_channel); + } else { + if (asc_dvc_varp->bus_type & ASC_IS_VL) { + busname = "VL"; + } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { + busname = "EISA"; + } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { + if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) + == ASC_IS_PCI_ULTRA) { + busname = "PCI Ultra"; + } else { + busname = "PCI"; + } + } else { + busname = "?"; + ASC_PRINT2 + ("advansys_info: board %d: unknown bus type %d\n", + boardp->id, asc_dvc_varp->bus_type); + } + /* Don't reference 'shost->n_io_port'; It may be truncated. */ + sprintf(info, + "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X", + ASC_VERSION, busname, + (ulong)shost->io_port, + (ulong)shost->io_port + boardp->asc_n_io_port - + 1, shost->irq); + } + } else { + /* + * Wide Adapter Information + * + * Memory-mapped I/O is used instead of I/O space to access + * the adapter, but display the I/O Port range. The Memory + * I/O address is displayed through the driver /proc file. + */ + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + iolen = ADV_3550_IOLEN; + widename = "Ultra-Wide"; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + iolen = ADV_38C0800_IOLEN; + widename = "Ultra2-Wide"; + } else { + iolen = ADV_38C1600_IOLEN; + widename = "Ultra3-Wide"; + } + sprintf(info, + "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X", + ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base, + (ulong)adv_dvc_varp->iop_base + iolen - 1, shost->irq); + } + ASC_ASSERT(strlen(info) < ASC_INFO_SIZE); + ASC_DBG(1, "advansys_info: end\n"); + return info; } /* @@ -5560,82 +4338,82 @@ advansys_info(struct Scsi_Host *shp) * in the 'scp' result field. */ static int -advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) +advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *)) { - struct Scsi_Host *shp; - asc_board_t *boardp; - ulong flags; - struct scsi_cmnd *done_scp; + struct Scsi_Host *shost; + asc_board_t *boardp; + ulong flags; + struct scsi_cmnd *done_scp; - shp = scp->device->host; - boardp = ASC_BOARDP(shp); - ASC_STATS(shp, queuecommand); + shost = scp->device->host; + boardp = ASC_BOARDP(shost); + ASC_STATS(shost, queuecommand); - /* host_lock taken by mid-level prior to call but need to protect */ - /* against own ISR */ - spin_lock_irqsave(&boardp->lock, flags); + /* host_lock taken by mid-level prior to call but need to protect */ + /* against own ISR */ + spin_lock_irqsave(&boardp->lock, flags); - /* - * Block new commands while handling a reset or abort request. - */ - if (boardp->flags & ASC_HOST_IN_RESET) { - ASC_DBG1(1, - "advansys_queuecommand: scp 0x%lx blocked for reset request\n", - (ulong) scp); - scp->result = HOST_BYTE(DID_RESET); - - /* - * Add blocked requests to the board's 'done' queue. The queued - * requests will be completed at the end of the abort or reset - * handling. - */ - asc_enqueue(&boardp->done, scp, ASC_BACK); - spin_unlock_irqrestore(&boardp->lock, flags); - return 0; - } + /* + * Block new commands while handling a reset or abort request. + */ + if (boardp->flags & ASC_HOST_IN_RESET) { + ASC_DBG1(1, + "advansys_queuecommand: scp 0x%lx blocked for reset request\n", + (ulong)scp); + scp->result = HOST_BYTE(DID_RESET); - /* - * Attempt to execute any waiting commands for the board. - */ - if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { - ASC_DBG(1, - "advansys_queuecommand: before asc_execute_queue() waiting\n"); - asc_execute_queue(&boardp->waiting); - } + /* + * Add blocked requests to the board's 'done' queue. The queued + * requests will be completed at the end of the abort or reset + * handling. + */ + asc_enqueue(&boardp->done, scp, ASC_BACK); + spin_unlock_irqrestore(&boardp->lock, flags); + return 0; + } - /* - * Save the function pointer to Linux mid-level 'done' function - * and attempt to execute the command. - * - * If ASC_NOERROR is returned the request has been added to the - * board's 'active' queue and will be completed by the interrupt - * handler. - * - * If ASC_BUSY is returned add the request to the board's per - * target waiting list. This is the first time the request has - * been tried. Add it to the back of the waiting list. It will be - * retried later. - * - * If an error occurred, the request will have been placed on the - * board's 'done' queue and must be completed before returning. - */ - scp->scsi_done = done; - switch (asc_execute_scsi_cmnd(scp)) { - case ASC_NOERROR: - break; - case ASC_BUSY: - asc_enqueue(&boardp->waiting, scp, ASC_BACK); - break; - case ASC_ERROR: - default: - done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); - /* Interrupts could be enabled here. */ - asc_scsi_done_list(done_scp); - break; - } - spin_unlock_irqrestore(&boardp->lock, flags); + /* + * Attempt to execute any waiting commands for the board. + */ + if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { + ASC_DBG(1, + "advansys_queuecommand: before asc_execute_queue() waiting\n"); + asc_execute_queue(&boardp->waiting); + } + + /* + * Save the function pointer to Linux mid-level 'done' function + * and attempt to execute the command. + * + * If ASC_NOERROR is returned the request has been added to the + * board's 'active' queue and will be completed by the interrupt + * handler. + * + * If ASC_BUSY is returned add the request to the board's per + * target waiting list. This is the first time the request has + * been tried. Add it to the back of the waiting list. It will be + * retried later. + * + * If an error occurred, the request will have been placed on the + * board's 'done' queue and must be completed before returning. + */ + scp->scsi_done = done; + switch (asc_execute_scsi_cmnd(scp)) { + case ASC_NOERROR: + break; + case ASC_BUSY: + asc_enqueue(&boardp->waiting, scp, ASC_BACK); + break; + case ASC_ERROR: + default: + done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); + /* Interrupts could be enabled here. */ + asc_scsi_done_list(done_scp); + break; + } + spin_unlock_irqrestore(&boardp->lock, flags); - return 0; + return 0; } /* @@ -5647,178 +4425,187 @@ advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) * sleeping is allowed and no locking other than for host structures is * required. Returns SUCCESS or FAILED. */ -static int -advansys_reset(struct scsi_cmnd *scp) +static int advansys_reset(struct scsi_cmnd *scp) { - struct Scsi_Host *shp; - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - ADV_DVC_VAR *adv_dvc_varp; - ulong flags; - struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; - struct scsi_cmnd *tscp, *new_last_scp; - int status; - int ret = SUCCESS; - - ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong) scp); + struct Scsi_Host *shost; + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; + ADV_DVC_VAR *adv_dvc_varp; + ulong flags; + struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; + struct scsi_cmnd *tscp, *new_last_scp; + int status; + int ret = SUCCESS; + + ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp); #ifdef ADVANSYS_STATS - if (scp->device->host != NULL) { - ASC_STATS(scp->device->host, reset); - } + if (scp->device->host != NULL) { + ASC_STATS(scp->device->host, reset); + } #endif /* ADVANSYS_STATS */ - if ((shp = scp->device->host) == NULL) { - scp->result = HOST_BYTE(DID_ERROR); - return FAILED; - } + if ((shost = scp->device->host) == NULL) { + scp->result = HOST_BYTE(DID_ERROR); + return FAILED; + } - boardp = ASC_BOARDP(shp); + boardp = ASC_BOARDP(shost); - ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n", - boardp->id); - /* - * Check for re-entrancy. - */ - spin_lock_irqsave(&boardp->lock, flags); - if (boardp->flags & ASC_HOST_IN_RESET) { - spin_unlock_irqrestore(&boardp->lock, flags); - return FAILED; - } - boardp->flags |= ASC_HOST_IN_RESET; - spin_unlock_irqrestore(&boardp->lock, flags); - - if (ASC_NARROW_BOARD(boardp)) { - /* - * Narrow Board - */ - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - - /* - * Reset the chip and SCSI bus. - */ - ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n"); - status = AscInitAsc1000Driver(asc_dvc_varp); - - /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */ - if (asc_dvc_varp->err_code) { - ASC_PRINT2( - "advansys_reset: board %d: SCSI bus reset error: 0x%x\n", - boardp->id, asc_dvc_varp->err_code); - ret = FAILED; - } else if (status) { - ASC_PRINT2( - "advansys_reset: board %d: SCSI bus reset warning: 0x%x\n", - boardp->id, status); - } else { - ASC_PRINT1( - "advansys_reset: board %d: SCSI bus reset successful.\n", - boardp->id); - } - - ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n"); + ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n", + boardp->id); + /* + * Check for re-entrancy. + */ spin_lock_irqsave(&boardp->lock, flags); + if (boardp->flags & ASC_HOST_IN_RESET) { + spin_unlock_irqrestore(&boardp->lock, flags); + return FAILED; + } + boardp->flags |= ASC_HOST_IN_RESET; + spin_unlock_irqrestore(&boardp->lock, flags); - } else { - /* - * Wide Board - * - * If the suggest reset bus flags are set, then reset the bus. - * Otherwise only reset the device. - */ - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - - /* - * Reset the target's SCSI bus. - */ - ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n"); - switch (AdvResetChipAndSB(adv_dvc_varp)) { - case ASC_TRUE: - ASC_PRINT1("advansys_reset: board %d: SCSI bus reset successful.\n", - boardp->id); - break; - case ASC_FALSE: - default: - ASC_PRINT1("advansys_reset: board %d: SCSI bus reset error.\n", - boardp->id); - ret = FAILED; - break; - } - spin_lock_irqsave(&boardp->lock, flags); - (void) AdvISR(adv_dvc_varp); - } - /* Board lock is held. */ + if (ASC_NARROW_BOARD(boardp)) { + /* + * Narrow Board + */ + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - /* - * Dequeue all board 'done' requests. A pointer to the last request - * is returned in 'last_scp'. - */ - done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL); + /* + * Reset the chip and SCSI bus. + */ + ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n"); + status = AscInitAsc1000Driver(asc_dvc_varp); + + /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */ + if (asc_dvc_varp->err_code) { + ASC_PRINT2 + ("advansys_reset: board %d: SCSI bus reset error: 0x%x\n", + boardp->id, asc_dvc_varp->err_code); + ret = FAILED; + } else if (status) { + ASC_PRINT2 + ("advansys_reset: board %d: SCSI bus reset warning: 0x%x\n", + boardp->id, status); + } else { + ASC_PRINT1 + ("advansys_reset: board %d: SCSI bus reset successful.\n", + boardp->id); + } + + ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n"); + spin_lock_irqsave(&boardp->lock, flags); - /* - * Dequeue all board 'active' requests for all devices and set - * the request status to DID_RESET. A pointer to the last request - * is returned in 'last_scp'. - */ - if (done_scp == NULL) { - done_scp = asc_dequeue_list(&boardp->active, &last_scp, ASC_TID_ALL); - for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - } else { - /* Append to 'done_scp' at the end with 'last_scp'. */ - ASC_ASSERT(last_scp != NULL); - last_scp->host_scribble = (unsigned char *)asc_dequeue_list( - &boardp->active, &new_last_scp, ASC_TID_ALL); - if (new_last_scp != NULL) { - ASC_ASSERT(REQPNEXT(last_scp) != NULL); - for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - last_scp = new_last_scp; - } - } + } else { + /* + * Wide Board + * + * If the suggest reset bus flags are set, then reset the bus. + * Otherwise only reset the device. + */ + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - /* - * Dequeue all 'waiting' requests and set the request status - * to DID_RESET. - */ - if (done_scp == NULL) { - done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, ASC_TID_ALL); - for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - } else { - /* Append to 'done_scp' at the end with 'last_scp'. */ - ASC_ASSERT(last_scp != NULL); - last_scp->host_scribble = (unsigned char *)asc_dequeue_list( - &boardp->waiting, &new_last_scp, ASC_TID_ALL); - if (new_last_scp != NULL) { - ASC_ASSERT(REQPNEXT(last_scp) != NULL); - for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - last_scp = new_last_scp; - } - } + /* + * Reset the target's SCSI bus. + */ + ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n"); + switch (AdvResetChipAndSB(adv_dvc_varp)) { + case ASC_TRUE: + ASC_PRINT1 + ("advansys_reset: board %d: SCSI bus reset successful.\n", + boardp->id); + break; + case ASC_FALSE: + default: + ASC_PRINT1 + ("advansys_reset: board %d: SCSI bus reset error.\n", + boardp->id); + ret = FAILED; + break; + } + spin_lock_irqsave(&boardp->lock, flags); + (void)AdvISR(adv_dvc_varp); + } + /* Board lock is held. */ + + /* + * Dequeue all board 'done' requests. A pointer to the last request + * is returned in 'last_scp'. + */ + done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL); + + /* + * Dequeue all board 'active' requests for all devices and set + * the request status to DID_RESET. A pointer to the last request + * is returned in 'last_scp'. + */ + if (done_scp == NULL) { + done_scp = + asc_dequeue_list(&boardp->active, &last_scp, ASC_TID_ALL); + for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { + tscp->result = HOST_BYTE(DID_RESET); + } + } else { + /* Append to 'done_scp' at the end with 'last_scp'. */ + ASC_ASSERT(last_scp != NULL); + last_scp->host_scribble = + (unsigned char *)asc_dequeue_list(&boardp->active, + &new_last_scp, + ASC_TID_ALL); + if (new_last_scp != NULL) { + ASC_ASSERT(REQPNEXT(last_scp) != NULL); + for (tscp = REQPNEXT(last_scp); tscp; + tscp = REQPNEXT(tscp)) { + tscp->result = HOST_BYTE(DID_RESET); + } + last_scp = new_last_scp; + } + } - /* Save the time of the most recently completed reset. */ - boardp->last_reset = jiffies; + /* + * Dequeue all 'waiting' requests and set the request status + * to DID_RESET. + */ + if (done_scp == NULL) { + done_scp = + asc_dequeue_list(&boardp->waiting, &last_scp, ASC_TID_ALL); + for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { + tscp->result = HOST_BYTE(DID_RESET); + } + } else { + /* Append to 'done_scp' at the end with 'last_scp'. */ + ASC_ASSERT(last_scp != NULL); + last_scp->host_scribble = + (unsigned char *)asc_dequeue_list(&boardp->waiting, + &new_last_scp, + ASC_TID_ALL); + if (new_last_scp != NULL) { + ASC_ASSERT(REQPNEXT(last_scp) != NULL); + for (tscp = REQPNEXT(last_scp); tscp; + tscp = REQPNEXT(tscp)) { + tscp->result = HOST_BYTE(DID_RESET); + } + last_scp = new_last_scp; + } + } - /* Clear reset flag. */ - boardp->flags &= ~ASC_HOST_IN_RESET; - spin_unlock_irqrestore(&boardp->lock, flags); + /* Save the time of the most recently completed reset. */ + boardp->last_reset = jiffies; - /* - * Complete all the 'done_scp' requests. - */ - if (done_scp != NULL) { - asc_scsi_done_list(done_scp); - } + /* Clear reset flag. */ + boardp->flags &= ~ASC_HOST_IN_RESET; + spin_unlock_irqrestore(&boardp->lock, flags); - ASC_DBG1(1, "advansys_reset: ret %d\n", ret); + /* + * Complete all the 'done_scp' requests. + */ + if (done_scp != NULL) { + asc_scsi_done_list(done_scp); + } - return ret; + ASC_DBG1(1, "advansys_reset: ret %d\n", ret); + + return ret; } /* @@ -5834,71 +4621,70 @@ advansys_reset(struct scsi_cmnd *scp) */ static int advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int ip[]) + sector_t capacity, int ip[]) { - asc_board_t *boardp; - - ASC_DBG(1, "advansys_biosparam: begin\n"); - ASC_STATS(sdev->host, biosparam); - boardp = ASC_BOARDP(sdev->host); - if (ASC_NARROW_BOARD(boardp)) { - if ((boardp->dvc_var.asc_dvc_var.dvc_cntl & - ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) { - ip[0] = 255; - ip[1] = 63; - } else { - ip[0] = 64; - ip[1] = 32; - } - } else { - if ((boardp->dvc_var.adv_dvc_var.bios_ctrl & - BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) { - ip[0] = 255; - ip[1] = 63; - } else { - ip[0] = 64; - ip[1] = 32; - } - } - ip[2] = (unsigned long)capacity / (ip[0] * ip[1]); - ASC_DBG(1, "advansys_biosparam: end\n"); - return 0; + asc_board_t *boardp; + + ASC_DBG(1, "advansys_biosparam: begin\n"); + ASC_STATS(sdev->host, biosparam); + boardp = ASC_BOARDP(sdev->host); + if (ASC_NARROW_BOARD(boardp)) { + if ((boardp->dvc_var.asc_dvc_var.dvc_cntl & + ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) { + ip[0] = 255; + ip[1] = 63; + } else { + ip[0] = 64; + ip[1] = 32; + } + } else { + if ((boardp->dvc_var.adv_dvc_var.bios_ctrl & + BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) { + ip[0] = 255; + ip[1] = 63; + } else { + ip[0] = 64; + ip[1] = 32; + } + } + ip[2] = (unsigned long)capacity / (ip[0] * ip[1]); + ASC_DBG(1, "advansys_biosparam: end\n"); + return 0; } -/* - * --- Loadable Driver Support - */ +static int __init advansys_detect(struct scsi_host_template *tpnt); +static int advansys_release(struct Scsi_Host *shp); static struct scsi_host_template driver_template = { - .proc_name = "advansys", + .proc_name = "advansys", #ifdef CONFIG_PROC_FS - .proc_info = advansys_proc_info, + .proc_info = advansys_proc_info, #endif - .name = "advansys", - .detect = advansys_detect, - .release = advansys_release, - .info = advansys_info, - .queuecommand = advansys_queuecommand, - .eh_bus_reset_handler = advansys_reset, - .bios_param = advansys_biosparam, - .slave_configure = advansys_slave_configure, - /* - * Because the driver may control an ISA adapter 'unchecked_isa_dma' - * must be set. The flag will be cleared in advansys_detect for non-ISA - * adapters. Refer to the comment in scsi_module.c for more information. - */ - .unchecked_isa_dma = 1, - /* - * All adapters controlled by this driver are capable of large - * scatter-gather lists. According to the mid-level SCSI documentation - * this obviates any performance gain provided by setting - * 'use_clustering'. But empirically while CPU utilization is increased - * by enabling clustering, I/O throughput increases as well. - */ - .use_clustering = ENABLE_CLUSTERING, + .name = "advansys", + .detect = advansys_detect, + .release = advansys_release, + .info = advansys_info, + .queuecommand = advansys_queuecommand, + .eh_bus_reset_handler = advansys_reset, + .bios_param = advansys_biosparam, + .slave_configure = advansys_slave_configure, + /* + * Because the driver may control an ISA adapter 'unchecked_isa_dma' + * must be set. The flag will be cleared in advansys_detect for non-ISA + * adapters. Refer to the comment in scsi_module.c for more information. + */ + .unchecked_isa_dma = 1, + /* + * All adapters controlled by this driver are capable of large + * scatter-gather lists. According to the mid-level SCSI documentation + * this obviates any performance gain provided by setting + * 'use_clustering'. But empirically while CPU utilization is increased + * by enabling clustering, I/O throughput increases as well. + */ + .use_clustering = ENABLE_CLUSTERING, }; -#include "scsi_module.c" +#include "scsi_module.c" /* * --- Miscellaneous Driver Functions @@ -5913,130 +4699,138 @@ static struct scsi_host_template driver_template = { * to the AdvanSys driver which is for a device sharing an interrupt with * an AdvanSys adapter. */ -STATIC irqreturn_t -advansys_interrupt(int irq, void *dev_id) +static irqreturn_t advansys_interrupt(int irq, void *dev_id) { - ulong flags; - int i; - asc_board_t *boardp; - struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; - struct scsi_cmnd *new_last_scp; - struct Scsi_Host *shp; - - ASC_DBG(1, "advansys_interrupt: begin\n"); + ulong flags; + int i; + asc_board_t *boardp; + struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; + struct scsi_cmnd *new_last_scp; + struct Scsi_Host *shost; + + ASC_DBG(1, "advansys_interrupt: begin\n"); + + /* + * Check for interrupts on all boards. + * AscISR() will call asc_isr_callback(). + */ + for (i = 0; i < asc_board_count; i++) { + shost = asc_host[i]; + boardp = ASC_BOARDP(shost); + ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n", + i, (ulong)boardp); + spin_lock_irqsave(&boardp->lock, flags); + if (ASC_NARROW_BOARD(boardp)) { + /* + * Narrow Board + */ + if (AscIsIntPending(shost->io_port)) { + ASC_STATS(shost, interrupt); + ASC_DBG(1, + "advansys_interrupt: before AscISR()\n"); + AscISR(&boardp->dvc_var.asc_dvc_var); + } + } else { + /* + * Wide Board + */ + ASC_DBG(1, "advansys_interrupt: before AdvISR()\n"); + if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { + ASC_STATS(shost, interrupt); + } + } - /* - * Check for interrupts on all boards. - * AscISR() will call asc_isr_callback(). - */ - for (i = 0; i < asc_board_count; i++) { - shp = asc_host[i]; - boardp = ASC_BOARDP(shp); - ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n", - i, (ulong) boardp); - spin_lock_irqsave(&boardp->lock, flags); - if (ASC_NARROW_BOARD(boardp)) { - /* - * Narrow Board - */ - if (AscIsIntPending(shp->io_port)) { - ASC_STATS(shp, interrupt); - ASC_DBG(1, "advansys_interrupt: before AscISR()\n"); - AscISR(&boardp->dvc_var.asc_dvc_var); - } - } else { - /* - * Wide Board - */ - ASC_DBG(1, "advansys_interrupt: before AdvISR()\n"); - if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { - ASC_STATS(shp, interrupt); - } - } - - /* - * Start waiting requests and create a list of completed requests. - * - * If a reset request is being performed for the board, the reset - * handler will complete pending requests after it has completed. - */ - if ((boardp->flags & ASC_HOST_IN_RESET) == 0) { - ASC_DBG2(1, "advansys_interrupt: done_scp 0x%lx, last_scp 0x%lx\n", - (ulong) done_scp, (ulong) last_scp); - - /* Start any waiting commands for the board. */ - if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { - ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n"); - asc_execute_queue(&boardp->waiting); - } - - /* - * Add to the list of requests that must be completed. - * - * 'done_scp' will always be NULL on the first iteration - * of this loop. 'last_scp' is set at the same time as - * 'done_scp'. - */ - if (done_scp == NULL) { - done_scp = asc_dequeue_list(&boardp->done, &last_scp, - ASC_TID_ALL); - } else { - ASC_ASSERT(last_scp != NULL); - last_scp->host_scribble = (unsigned char *)asc_dequeue_list( - &boardp->done, &new_last_scp, ASC_TID_ALL); - if (new_last_scp != NULL) { - ASC_ASSERT(REQPNEXT(last_scp) != NULL); - last_scp = new_last_scp; - } - } - } - spin_unlock_irqrestore(&boardp->lock, flags); - } + /* + * Start waiting requests and create a list of completed requests. + * + * If a reset request is being performed for the board, the reset + * handler will complete pending requests after it has completed. + */ + if ((boardp->flags & ASC_HOST_IN_RESET) == 0) { + ASC_DBG2(1, + "advansys_interrupt: done_scp 0x%lx, last_scp 0x%lx\n", + (ulong)done_scp, (ulong)last_scp); + + /* Start any waiting commands for the board. */ + if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { + ASC_DBG(1, + "advansys_interrupt: before asc_execute_queue()\n"); + asc_execute_queue(&boardp->waiting); + } + + /* + * Add to the list of requests that must be completed. + * + * 'done_scp' will always be NULL on the first iteration + * of this loop. 'last_scp' is set at the same time as + * 'done_scp'. + */ + if (done_scp == NULL) { + done_scp = + asc_dequeue_list(&boardp->done, &last_scp, + ASC_TID_ALL); + } else { + ASC_ASSERT(last_scp != NULL); + last_scp->host_scribble = + (unsigned char *)asc_dequeue_list(&boardp-> + done, + &new_last_scp, + ASC_TID_ALL); + if (new_last_scp != NULL) { + ASC_ASSERT(REQPNEXT(last_scp) != NULL); + last_scp = new_last_scp; + } + } + } + spin_unlock_irqrestore(&boardp->lock, flags); + } - /* - * If interrupts were enabled on entry, then they - * are now enabled here. - * - * Complete all requests on the done list. - */ + /* + * If interrupts were enabled on entry, then they + * are now enabled here. + * + * Complete all requests on the done list. + */ - asc_scsi_done_list(done_scp); + asc_scsi_done_list(done_scp); - ASC_DBG(1, "advansys_interrupt: end\n"); - return IRQ_HANDLED; + ASC_DBG(1, "advansys_interrupt: end\n"); + return IRQ_HANDLED; } /* * Set the number of commands to queue per device for the * specified host adapter. */ -STATIC int -advansys_slave_configure(struct scsi_device *device) +static int advansys_slave_configure(struct scsi_device *device) { - asc_board_t *boardp; + asc_board_t *boardp; - boardp = ASC_BOARDP(device->host); - boardp->flags |= ASC_SELECT_QUEUE_DEPTHS; - /* - * Save a pointer to the device and set its initial/maximum - * queue depth. Only save the pointer for a lun0 dev though. - */ - if(device->lun == 0) - boardp->device[device->id] = device; - if(device->tagged_supported) { - if (ASC_NARROW_BOARD(boardp)) { - scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, - boardp->dvc_var.asc_dvc_var.max_dvc_qng[device->id]); - } else { - scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, - boardp->dvc_var.adv_dvc_var.max_dvc_qng); - } - } else { - scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun); - } - ASC_DBG4(1, "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n", - (ulong) device, (ulong) boardp, device->id, device->queue_depth); - return 0; + boardp = ASC_BOARDP(device->host); + boardp->flags |= ASC_SELECT_QUEUE_DEPTHS; + /* + * Save a pointer to the device and set its initial/maximum + * queue depth. Only save the pointer for a lun0 dev though. + */ + if (device->lun == 0) + boardp->device[device->id] = device; + if (device->tagged_supported) { + if (ASC_NARROW_BOARD(boardp)) { + scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, + boardp->dvc_var.asc_dvc_var. + max_dvc_qng[device->id]); + } else { + scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, + boardp->dvc_var.adv_dvc_var. + max_dvc_qng); + } + } else { + scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun); + } + ASC_DBG4(1, + "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n", + (ulong)device, (ulong)boardp, device->id, device->queue_depth); + return 0; } /* @@ -6045,43 +4839,44 @@ advansys_slave_configure(struct scsi_device *device) * * Interrupts can be enabled on entry. */ -STATIC void -asc_scsi_done_list(struct scsi_cmnd *scp) +static void asc_scsi_done_list(struct scsi_cmnd *scp) { - struct scsi_cmnd *tscp; + struct scsi_cmnd *tscp; - ASC_DBG(2, "asc_scsi_done_list: begin\n"); - while (scp != NULL) { - asc_board_t *boardp; - struct device *dev; + ASC_DBG(2, "asc_scsi_done_list: begin\n"); + while (scp != NULL) { + asc_board_t *boardp; + struct device *dev; - ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong) scp); - tscp = REQPNEXT(scp); - scp->host_scribble = NULL; + ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp); + tscp = REQPNEXT(scp); + scp->host_scribble = NULL; - boardp = ASC_BOARDP(scp->device->host); + boardp = ASC_BOARDP(scp->device->host); - if (ASC_NARROW_BOARD(boardp)) - dev = boardp->dvc_cfg.asc_dvc_cfg.dev; - else - dev = boardp->dvc_cfg.adv_dvc_cfg.dev; + if (ASC_NARROW_BOARD(boardp)) + dev = boardp->dvc_cfg.asc_dvc_cfg.dev; + else + dev = boardp->dvc_cfg.adv_dvc_cfg.dev; - if (scp->use_sg) - dma_unmap_sg(dev, (struct scatterlist *)scp->request_buffer, - scp->use_sg, scp->sc_data_direction); - else if (scp->request_bufflen) - dma_unmap_single(dev, scp->SCp.dma_handle, - scp->request_bufflen, scp->sc_data_direction); + if (scp->use_sg) + dma_unmap_sg(dev, + (struct scatterlist *)scp->request_buffer, + scp->use_sg, scp->sc_data_direction); + else if (scp->request_bufflen) + dma_unmap_single(dev, scp->SCp.dma_handle, + scp->request_bufflen, + scp->sc_data_direction); - ASC_STATS(scp->device->host, done); - ASC_ASSERT(scp->scsi_done != NULL); + ASC_STATS(scp->device->host, done); + ASC_ASSERT(scp->scsi_done != NULL); - scp->scsi_done(scp); + scp->scsi_done(scp); - scp = tscp; - } - ASC_DBG(2, "asc_scsi_done_list: done\n"); - return; + scp = tscp; + } + ASC_DBG(2, "asc_scsi_done_list: done\n"); + return; } /* @@ -6130,168 +4925,170 @@ asc_scsi_done_list(struct scsi_cmnd *scp) * If ASC_BUSY is returned the request will be enqueued by the * caller on the target's waiting queue and re-tried later. */ -STATIC int -asc_execute_scsi_cmnd(struct scsi_cmnd *scp) +static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) { - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - ADV_DVC_VAR *adv_dvc_varp; - ADV_SCSI_REQ_Q *adv_scsiqp; - struct scsi_device *device; - int ret; - - ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n", - (ulong) scp, (ulong) scp->scsi_done); - - boardp = ASC_BOARDP(scp->device->host); - device = boardp->device[scp->device->id]; - - if (ASC_NARROW_BOARD(boardp)) { - /* - * Build and execute Narrow Board request. - */ - - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - - /* - * Build Asc Library request structure using the - * global structures 'asc_scsi_req' and 'asc_sg_head'. - * - * If an error is returned, then the request has been - * queued on the board done queue. It will be completed - * by the caller. - * - * asc_build_req() can not return ASC_BUSY. - */ - if (asc_build_req(boardp, scp) == ASC_ERROR) { - ASC_STATS(scp->device->host, build_error); - return ASC_ERROR; - } - - /* - * Execute the command. If there is no error, add the command - * to the active queue. - */ - switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { - case ASC_NOERROR: - ASC_STATS(scp->device->host, exe_noerror); - /* - * Increment monotonically increasing per device successful - * request counter. Wrapping doesn't matter. - */ - boardp->reqcnt[scp->device->id]++; - asc_enqueue(&boardp->active, scp, ASC_BACK); - ASC_DBG(1, - "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n"); - break; - case ASC_BUSY: - /* - * Caller will enqueue request on the target's waiting queue - * and retry later. - */ - ASC_STATS(scp->device->host, exe_busy); - break; - case ASC_ERROR: - ASC_PRINT2( -"asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n", - boardp->id, asc_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_error); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; - default: - ASC_PRINT2( -"asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code 0x%x\n", - boardp->id, asc_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_unknown); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; - } - } else { - /* - * Build and execute Wide Board request. - */ - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - - /* - * Build and get a pointer to an Adv Library request structure. - * - * If the request is successfully built then send it below, - * otherwise return with an error. - */ - switch (adv_build_req(boardp, scp, &adv_scsiqp)) { - case ASC_NOERROR: - ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n"); - break; - case ASC_BUSY: - ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n"); - /* - * If busy is returned the request has not been enqueued. - * It will be enqueued by the caller on the target's waiting - * queue and retried later. - * - * The asc_stats fields 'adv_build_noreq' and 'adv_build_nosg' - * count wide board busy conditions. They are updated in - * adv_build_req and adv_get_sglist, respectively. - */ - return ASC_BUSY; - case ASC_ERROR: - /* - * If an error is returned, then the request has been - * queued on the board done queue. It will be completed - * by the caller. - */ - default: - ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n"); - ASC_STATS(scp->device->host, build_error); - return ASC_ERROR; - } - - /* - * Execute the command. If there is no error, add the command - * to the active queue. - */ - switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) { - case ASC_NOERROR: - ASC_STATS(scp->device->host, exe_noerror); - /* - * Increment monotonically increasing per device successful - * request counter. Wrapping doesn't matter. - */ - boardp->reqcnt[scp->device->id]++; - asc_enqueue(&boardp->active, scp, ASC_BACK); - ASC_DBG(1, - "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n"); - break; - case ASC_BUSY: - /* - * Caller will enqueue request on the target's waiting queue - * and retry later. - */ - ASC_STATS(scp->device->host, exe_busy); - break; - case ASC_ERROR: - ASC_PRINT2( -"asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n", - boardp->id, adv_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_error); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; - default: - ASC_PRINT2( -"asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code 0x%x\n", - boardp->id, adv_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_unknown); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; - } - } + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; + ADV_DVC_VAR *adv_dvc_varp; + ADV_SCSI_REQ_Q *adv_scsiqp; + struct scsi_device *device; + int ret; + + ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n", + (ulong)scp, (ulong)scp->scsi_done); + + boardp = ASC_BOARDP(scp->device->host); + device = boardp->device[scp->device->id]; + + if (ASC_NARROW_BOARD(boardp)) { + /* + * Build and execute Narrow Board request. + */ + + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + + /* + * Build Asc Library request structure using the + * global structures 'asc_scsi_req' and 'asc_sg_head'. + * + * If an error is returned, then the request has been + * queued on the board done queue. It will be completed + * by the caller. + * + * asc_build_req() can not return ASC_BUSY. + */ + if (asc_build_req(boardp, scp) == ASC_ERROR) { + ASC_STATS(scp->device->host, build_error); + return ASC_ERROR; + } - ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); - return ret; + /* + * Execute the command. If there is no error, add the command + * to the active queue. + */ + switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { + case ASC_NOERROR: + ASC_STATS(scp->device->host, exe_noerror); + /* + * Increment monotonically increasing per device successful + * request counter. Wrapping doesn't matter. + */ + boardp->reqcnt[scp->device->id]++; + asc_enqueue(&boardp->active, scp, ASC_BACK); + ASC_DBG(1, + "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n"); + break; + case ASC_BUSY: + /* + * Caller will enqueue request on the target's waiting queue + * and retry later. + */ + ASC_STATS(scp->device->host, exe_busy); + break; + case ASC_ERROR: + ASC_PRINT2 + ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n", + boardp->id, asc_dvc_varp->err_code); + ASC_STATS(scp->device->host, exe_error); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + break; + default: + ASC_PRINT2 + ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code 0x%x\n", + boardp->id, asc_dvc_varp->err_code); + ASC_STATS(scp->device->host, exe_unknown); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + break; + } + } else { + /* + * Build and execute Wide Board request. + */ + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; + + /* + * Build and get a pointer to an Adv Library request structure. + * + * If the request is successfully built then send it below, + * otherwise return with an error. + */ + switch (adv_build_req(boardp, scp, &adv_scsiqp)) { + case ASC_NOERROR: + ASC_DBG(3, + "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n"); + break; + case ASC_BUSY: + ASC_DBG(1, + "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n"); + /* + * If busy is returned the request has not been enqueued. + * It will be enqueued by the caller on the target's waiting + * queue and retried later. + * + * The asc_stats fields 'adv_build_noreq' and 'adv_build_nosg' + * count wide board busy conditions. They are updated in + * adv_build_req and adv_get_sglist, respectively. + */ + return ASC_BUSY; + case ASC_ERROR: + /* + * If an error is returned, then the request has been + * queued on the board done queue. It will be completed + * by the caller. + */ + default: + ASC_DBG(1, + "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n"); + ASC_STATS(scp->device->host, build_error); + return ASC_ERROR; + } + + /* + * Execute the command. If there is no error, add the command + * to the active queue. + */ + switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) { + case ASC_NOERROR: + ASC_STATS(scp->device->host, exe_noerror); + /* + * Increment monotonically increasing per device successful + * request counter. Wrapping doesn't matter. + */ + boardp->reqcnt[scp->device->id]++; + asc_enqueue(&boardp->active, scp, ASC_BACK); + ASC_DBG(1, + "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n"); + break; + case ASC_BUSY: + /* + * Caller will enqueue request on the target's waiting queue + * and retry later. + */ + ASC_STATS(scp->device->host, exe_busy); + break; + case ASC_ERROR: + ASC_PRINT2 + ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n", + boardp->id, adv_dvc_varp->err_code); + ASC_STATS(scp->device->host, exe_error); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + break; + default: + ASC_PRINT2 + ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code 0x%x\n", + boardp->id, adv_dvc_varp->err_code); + ASC_STATS(scp->device->host, exe_unknown); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + break; + } + } + + ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); + return ret; } /* @@ -6303,131 +5100,140 @@ asc_execute_scsi_cmnd(struct scsi_cmnd *scp) * If an error occurs, then queue the request on the board done * queue and return ASC_ERROR. */ -STATIC int -asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) +static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) { - struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev; - - /* - * Mutually exclusive access is required to 'asc_scsi_q' and - * 'asc_sg_head' until after the request is started. - */ - memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q)); - - /* - * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. - */ - asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp); - - /* - * Build the ASC_SCSI_Q request. - * - * For narrow boards a CDB length maximum of 12 bytes - * is supported. - */ - if (scp->cmd_len > ASC_MAX_CDB_LEN) { - ASC_PRINT3( -"asc_build_req: board %d: cmd_len %d > ASC_MAX_CDB_LEN %d\n", - boardp->id, scp->cmd_len, ASC_MAX_CDB_LEN); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - asc_scsi_q.cdbptr = &scp->cmnd[0]; - asc_scsi_q.q2.cdb_len = scp->cmd_len; - asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); - asc_scsi_q.q1.target_lun = scp->device->lun; - asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); - asc_scsi_q.q1.sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); - asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); + struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev; + + /* + * Mutually exclusive access is required to 'asc_scsi_q' and + * 'asc_sg_head' until after the request is started. + */ + memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q)); + + /* + * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. + */ + asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp); + + /* + * Build the ASC_SCSI_Q request. + * + * For narrow boards a CDB length maximum of 12 bytes + * is supported. + */ + if (scp->cmd_len > ASC_MAX_CDB_LEN) { + ASC_PRINT3 + ("asc_build_req: board %d: cmd_len %d > ASC_MAX_CDB_LEN %d\n", + boardp->id, scp->cmd_len, ASC_MAX_CDB_LEN); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + return ASC_ERROR; + } + asc_scsi_q.cdbptr = &scp->cmnd[0]; + asc_scsi_q.q2.cdb_len = scp->cmd_len; + asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); + asc_scsi_q.q1.target_lun = scp->device->lun; + asc_scsi_q.q2.target_ix = + ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); + asc_scsi_q.q1.sense_addr = + cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); + asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); + + /* + * If there are any outstanding requests for the current target, + * then every 255th request send an ORDERED request. This heuristic + * tries to retain the benefit of request sorting while preventing + * request starvation. 255 is the max number of tags or pending commands + * a device may have outstanding. + * + * The request count is incremented below for every successfully + * started request. + * + */ + if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && + (boardp->reqcnt[scp->device->id] % 255) == 0) { + asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG; + } else { + asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; + } - /* - * If there are any outstanding requests for the current target, - * then every 255th request send an ORDERED request. This heuristic - * tries to retain the benefit of request sorting while preventing - * request starvation. 255 is the max number of tags or pending commands - * a device may have outstanding. - * - * The request count is incremented below for every successfully - * started request. - * - */ - if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && - (boardp->reqcnt[scp->device->id] % 255) == 0) { - asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG; - } else { - asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; - } + /* + * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather + * buffer command. + */ + if (scp->use_sg == 0) { + /* + * CDB request of single contiguous buffer. + */ + ASC_STATS(scp->device->host, cont_cnt); + scp->SCp.dma_handle = scp->request_bufflen ? + dma_map_single(dev, scp->request_buffer, + scp->request_bufflen, + scp->sc_data_direction) : 0; + asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); + asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); + ASC_STATS_ADD(scp->device->host, cont_xfer, + ASC_CEILING(scp->request_bufflen, 512)); + asc_scsi_q.q1.sg_queue_cnt = 0; + asc_scsi_q.sg_head = NULL; + } else { + /* + * CDB scatter-gather request list. + */ + int sgcnt; + int use_sg; + struct scatterlist *slp; + + slp = (struct scatterlist *)scp->request_buffer; + use_sg = + dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); + + if (use_sg > scp->device->host->sg_tablesize) { + ASC_PRINT3 + ("asc_build_req: board %d: use_sg %d > sg_tablesize %d\n", + boardp->id, use_sg, + scp->device->host->sg_tablesize); + dma_unmap_sg(dev, slp, scp->use_sg, + scp->sc_data_direction); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + return ASC_ERROR; + } + + ASC_STATS(scp->device->host, sg_cnt); - /* - * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather - * buffer command. - */ - if (scp->use_sg == 0) { - /* - * CDB request of single contiguous buffer. - */ - ASC_STATS(scp->device->host, cont_cnt); - scp->SCp.dma_handle = scp->request_bufflen ? - dma_map_single(dev, scp->request_buffer, - scp->request_bufflen, scp->sc_data_direction) : 0; - asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); - asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); - ASC_STATS_ADD(scp->device->host, cont_xfer, - ASC_CEILING(scp->request_bufflen, 512)); - asc_scsi_q.q1.sg_queue_cnt = 0; - asc_scsi_q.sg_head = NULL; - } else { - /* - * CDB scatter-gather request list. - */ - int sgcnt; - int use_sg; - struct scatterlist *slp; + /* + * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q + * structure to point to it. + */ + memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD)); + + asc_scsi_q.q1.cntl |= QC_SG_HEAD; + asc_scsi_q.sg_head = &asc_sg_head; + asc_scsi_q.q1.data_cnt = 0; + asc_scsi_q.q1.data_addr = 0; + /* This is a byte value, otherwise it would need to be swapped. */ + asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; + ASC_STATS_ADD(scp->device->host, sg_elem, + asc_sg_head.entry_cnt); - slp = (struct scatterlist *)scp->request_buffer; - use_sg = dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - - if (use_sg > scp->device->host->sg_tablesize) { - ASC_PRINT3( -"asc_build_req: board %d: use_sg %d > sg_tablesize %d\n", - boardp->id, use_sg, scp->device->host->sg_tablesize); - dma_unmap_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - - ASC_STATS(scp->device->host, sg_cnt); - - /* - * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q - * structure to point to it. - */ - memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD)); - - asc_scsi_q.q1.cntl |= QC_SG_HEAD; - asc_scsi_q.sg_head = &asc_sg_head; - asc_scsi_q.q1.data_cnt = 0; - asc_scsi_q.q1.data_addr = 0; - /* This is a byte value, otherwise it would need to be swapped. */ - asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; - ASC_STATS_ADD(scp->device->host, sg_elem, asc_sg_head.entry_cnt); - - /* - * Convert scatter-gather list into ASC_SG_HEAD list. - */ - for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { - asc_sg_head.sg_list[sgcnt].addr = cpu_to_le32(sg_dma_address(slp)); - asc_sg_head.sg_list[sgcnt].bytes = cpu_to_le32(sg_dma_len(slp)); - ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512)); - } - } + /* + * Convert scatter-gather list into ASC_SG_HEAD list. + */ + for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { + asc_sg_head.sg_list[sgcnt].addr = + cpu_to_le32(sg_dma_address(slp)); + asc_sg_head.sg_list[sgcnt].bytes = + cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, sg_xfer, + ASC_CEILING(sg_dma_len(slp), 512)); + } + } - ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q); - ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); + ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q); + ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); - return ASC_NOERROR; + return ASC_NOERROR; } /* @@ -6440,162 +5246,168 @@ asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) * microcode for DMA addresses or math operations are byte swapped * to little-endian order. */ -STATIC int +static int adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, - ADV_SCSI_REQ_Q **adv_scsiqpp) + ADV_SCSI_REQ_Q **adv_scsiqpp) { - adv_req_t *reqp; - ADV_SCSI_REQ_Q *scsiqp; - int i; - int ret; - struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev; - - /* - * Allocate an adv_req_t structure from the board to execute - * the command. - */ - if (boardp->adv_reqp == NULL) { - ASC_DBG(1, "adv_build_req: no free adv_req_t\n"); - ASC_STATS(scp->device->host, adv_build_noreq); - return ASC_BUSY; - } else { - reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp->next_reqp; - reqp->next_reqp = NULL; - } - - /* - * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. - */ - scsiqp = (ADV_SCSI_REQ_Q *) ADV_32BALIGN(&reqp->scsi_req_q); - - /* - * Initialize the structure. - */ - scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0; - - /* - * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. - */ - scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp); - - /* - * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. - */ - reqp->cmndp = scp; + adv_req_t *reqp; + ADV_SCSI_REQ_Q *scsiqp; + int i; + int ret; + struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev; + + /* + * Allocate an adv_req_t structure from the board to execute + * the command. + */ + if (boardp->adv_reqp == NULL) { + ASC_DBG(1, "adv_build_req: no free adv_req_t\n"); + ASC_STATS(scp->device->host, adv_build_noreq); + return ASC_BUSY; + } else { + reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp->next_reqp; + reqp->next_reqp = NULL; + } - /* - * Build the ADV_SCSI_REQ_Q request. - */ + /* + * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. + */ + scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); + + /* + * Initialize the structure. + */ + scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0; + + /* + * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. + */ + scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp); + + /* + * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. + */ + reqp->cmndp = scp; + + /* + * Build the ADV_SCSI_REQ_Q request. + */ + + /* + * Set CDB length and copy it to the request structure. + * For wide boards a CDB length maximum of 16 bytes + * is supported. + */ + if (scp->cmd_len > ADV_MAX_CDB_LEN) { + ASC_PRINT3 + ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n", + boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + return ASC_ERROR; + } + scsiqp->cdb_len = scp->cmd_len; + /* Copy first 12 CDB bytes to cdb[]. */ + for (i = 0; i < scp->cmd_len && i < 12; i++) { + scsiqp->cdb[i] = scp->cmnd[i]; + } + /* Copy last 4 CDB bytes, if present, to cdb16[]. */ + for (; i < scp->cmd_len; i++) { + scsiqp->cdb16[i - 12] = scp->cmnd[i]; + } - /* - * Set CDB length and copy it to the request structure. - * For wide boards a CDB length maximum of 16 bytes - * is supported. - */ - if (scp->cmd_len > ADV_MAX_CDB_LEN) { - ASC_PRINT3( -"adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n", - boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - scsiqp->cdb_len = scp->cmd_len; - /* Copy first 12 CDB bytes to cdb[]. */ - for (i = 0; i < scp->cmd_len && i < 12; i++) { - scsiqp->cdb[i] = scp->cmnd[i]; - } - /* Copy last 4 CDB bytes, if present, to cdb16[]. */ - for (; i < scp->cmd_len; i++) { - scsiqp->cdb16[i - 12] = scp->cmnd[i]; - } + scsiqp->target_id = scp->device->id; + scsiqp->target_lun = scp->device->lun; - scsiqp->target_id = scp->device->id; - scsiqp->target_lun = scp->device->lun; + scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); + scsiqp->sense_len = sizeof(scp->sense_buffer); - scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); - scsiqp->sense_len = sizeof(scp->sense_buffer); + /* + * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather + * buffer command. + */ - /* - * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather - * buffer command. - */ - - scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); - scsiqp->vdata_addr = scp->request_buffer; - scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer)); - - if (scp->use_sg == 0) { - /* - * CDB request of single contiguous buffer. - */ - reqp->sgblkp = NULL; scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); - if (scp->request_bufflen) { - scsiqp->vdata_addr = scp->request_buffer; - scp->SCp.dma_handle = - dma_map_single(dev, scp->request_buffer, - scp->request_bufflen, scp->sc_data_direction); - } else { - scsiqp->vdata_addr = NULL; - scp->SCp.dma_handle = 0; - } - scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle); - scsiqp->sg_list_ptr = NULL; - scsiqp->sg_real_addr = 0; - ASC_STATS(scp->device->host, cont_cnt); - ASC_STATS_ADD(scp->device->host, cont_xfer, - ASC_CEILING(scp->request_bufflen, 512)); - } else { - /* - * CDB scatter-gather request list. - */ - struct scatterlist *slp; - int use_sg; + scsiqp->vdata_addr = scp->request_buffer; + scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer)); - slp = (struct scatterlist *)scp->request_buffer; - use_sg = dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - - if (use_sg > ADV_MAX_SG_LIST) { - ASC_PRINT3( -"adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n", - boardp->id, use_sg, scp->device->host->sg_tablesize); - dma_unmap_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - - /* - * Free the 'adv_req_t' structure by adding it back to the - * board free list. - */ - reqp->next_reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp; - - return ASC_ERROR; - } - - if ((ret = adv_get_sglist(boardp, reqp, scp, use_sg)) != ADV_SUCCESS) { - /* - * Free the adv_req_t structure by adding it back to the - * board free list. - */ - reqp->next_reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp; - - return ret; - } - - ASC_STATS(scp->device->host, sg_cnt); - ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); - } + if (scp->use_sg == 0) { + /* + * CDB request of single contiguous buffer. + */ + reqp->sgblkp = NULL; + scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); + if (scp->request_bufflen) { + scsiqp->vdata_addr = scp->request_buffer; + scp->SCp.dma_handle = + dma_map_single(dev, scp->request_buffer, + scp->request_bufflen, + scp->sc_data_direction); + } else { + scsiqp->vdata_addr = NULL; + scp->SCp.dma_handle = 0; + } + scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle); + scsiqp->sg_list_ptr = NULL; + scsiqp->sg_real_addr = 0; + ASC_STATS(scp->device->host, cont_cnt); + ASC_STATS_ADD(scp->device->host, cont_xfer, + ASC_CEILING(scp->request_bufflen, 512)); + } else { + /* + * CDB scatter-gather request list. + */ + struct scatterlist *slp; + int use_sg; + + slp = (struct scatterlist *)scp->request_buffer; + use_sg = + dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); + + if (use_sg > ADV_MAX_SG_LIST) { + ASC_PRINT3 + ("adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n", + boardp->id, use_sg, + scp->device->host->sg_tablesize); + dma_unmap_sg(dev, slp, scp->use_sg, + scp->sc_data_direction); + scp->result = HOST_BYTE(DID_ERROR); + asc_enqueue(&boardp->done, scp, ASC_BACK); + + /* + * Free the 'adv_req_t' structure by adding it back to the + * board free list. + */ + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; + + return ASC_ERROR; + } + + if ((ret = + adv_get_sglist(boardp, reqp, scp, + use_sg)) != ADV_SUCCESS) { + /* + * Free the adv_req_t structure by adding it back to the + * board free list. + */ + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; + + return ret; + } + + ASC_STATS(scp->device->host, sg_cnt); + ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); + } - ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); - ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); + ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); + ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); - *adv_scsiqpp = scsiqp; + *adv_scsiqpp = scsiqp; - return ASC_NOERROR; + return ASC_NOERROR; } /* @@ -6610,108 +5422,109 @@ adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, * ADV_SUCCESS(1) - SG List successfully created * ADV_ERROR(-1) - SG List creation failed */ -STATIC int -adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, int use_sg) +static int +adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, + int use_sg) { - adv_sgblk_t *sgblkp; - ADV_SCSI_REQ_Q *scsiqp; - struct scatterlist *slp; - int sg_elem_cnt; - ADV_SG_BLOCK *sg_block, *prev_sg_block; - ADV_PADDR sg_block_paddr; - int i; - - scsiqp = (ADV_SCSI_REQ_Q *) ADV_32BALIGN(&reqp->scsi_req_q); - slp = (struct scatterlist *) scp->request_buffer; - sg_elem_cnt = use_sg; - prev_sg_block = NULL; - reqp->sgblkp = NULL; - - do - { - /* - * Allocate a 'adv_sgblk_t' structure from the board free - * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK - * (15) scatter-gather elements. - */ - if ((sgblkp = boardp->adv_sgblkp) == NULL) { - ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n"); - ASC_STATS(scp->device->host, adv_build_nosg); - - /* - * Allocation failed. Free 'adv_sgblk_t' structures already - * allocated for the request. - */ - while ((sgblkp = reqp->sgblkp) != NULL) - { - /* Remove 'sgblkp' from the request list. */ - reqp->sgblkp = sgblkp->next_sgblkp; - - /* Add 'sgblkp' to the board free list. */ - sgblkp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgblkp; - } - return ASC_BUSY; - } else { - /* Complete 'adv_sgblk_t' board allocation. */ - boardp->adv_sgblkp = sgblkp->next_sgblkp; - sgblkp->next_sgblkp = NULL; - - /* - * Get 8 byte aligned virtual and physical addresses for - * the allocated ADV_SG_BLOCK structure. - */ - sg_block = (ADV_SG_BLOCK *) ADV_8BALIGN(&sgblkp->sg_block); - sg_block_paddr = virt_to_bus(sg_block); - - /* - * Check if this is the first 'adv_sgblk_t' for the request. - */ - if (reqp->sgblkp == NULL) - { - /* Request's first scatter-gather block. */ - reqp->sgblkp = sgblkp; - - /* - * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical - * address pointers. - */ - scsiqp->sg_list_ptr = sg_block; - scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr); - } else - { - /* Request's second or later scatter-gather block. */ - sgblkp->next_sgblkp = reqp->sgblkp; - reqp->sgblkp = sgblkp; - - /* - * Point the previous ADV_SG_BLOCK structure to - * the newly allocated ADV_SG_BLOCK structure. - */ - ASC_ASSERT(prev_sg_block != NULL); - prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr); - } - } - - for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) - { - sg_block->sg_list[i].sg_addr = cpu_to_le32(sg_dma_address(slp)); - sg_block->sg_list[i].sg_count = cpu_to_le32(sg_dma_len(slp)); - ASC_STATS_ADD(scp->device->host, sg_xfer, ASC_CEILING(sg_dma_len(slp), 512)); - - if (--sg_elem_cnt == 0) - { /* Last ADV_SG_BLOCK and scatter-gather entry. */ - sg_block->sg_cnt = i + 1; - sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */ - return ADV_SUCCESS; - } - slp++; - } - sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; - prev_sg_block = sg_block; - } - while (1); - /* NOTREACHED */ + adv_sgblk_t *sgblkp; + ADV_SCSI_REQ_Q *scsiqp; + struct scatterlist *slp; + int sg_elem_cnt; + ADV_SG_BLOCK *sg_block, *prev_sg_block; + ADV_PADDR sg_block_paddr; + int i; + + scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); + slp = (struct scatterlist *)scp->request_buffer; + sg_elem_cnt = use_sg; + prev_sg_block = NULL; + reqp->sgblkp = NULL; + + do { + /* + * Allocate a 'adv_sgblk_t' structure from the board free + * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK + * (15) scatter-gather elements. + */ + if ((sgblkp = boardp->adv_sgblkp) == NULL) { + ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n"); + ASC_STATS(scp->device->host, adv_build_nosg); + + /* + * Allocation failed. Free 'adv_sgblk_t' structures already + * allocated for the request. + */ + while ((sgblkp = reqp->sgblkp) != NULL) { + /* Remove 'sgblkp' from the request list. */ + reqp->sgblkp = sgblkp->next_sgblkp; + + /* Add 'sgblkp' to the board free list. */ + sgblkp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgblkp; + } + return ASC_BUSY; + } else { + /* Complete 'adv_sgblk_t' board allocation. */ + boardp->adv_sgblkp = sgblkp->next_sgblkp; + sgblkp->next_sgblkp = NULL; + + /* + * Get 8 byte aligned virtual and physical addresses for + * the allocated ADV_SG_BLOCK structure. + */ + sg_block = + (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block); + sg_block_paddr = virt_to_bus(sg_block); + + /* + * Check if this is the first 'adv_sgblk_t' for the request. + */ + if (reqp->sgblkp == NULL) { + /* Request's first scatter-gather block. */ + reqp->sgblkp = sgblkp; + + /* + * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical + * address pointers. + */ + scsiqp->sg_list_ptr = sg_block; + scsiqp->sg_real_addr = + cpu_to_le32(sg_block_paddr); + } else { + /* Request's second or later scatter-gather block. */ + sgblkp->next_sgblkp = reqp->sgblkp; + reqp->sgblkp = sgblkp; + + /* + * Point the previous ADV_SG_BLOCK structure to + * the newly allocated ADV_SG_BLOCK structure. + */ + ASC_ASSERT(prev_sg_block != NULL); + prev_sg_block->sg_ptr = + cpu_to_le32(sg_block_paddr); + } + } + + for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) { + sg_block->sg_list[i].sg_addr = + cpu_to_le32(sg_dma_address(slp)); + sg_block->sg_list[i].sg_count = + cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, sg_xfer, + ASC_CEILING(sg_dma_len(slp), 512)); + + if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */ + sg_block->sg_cnt = i + 1; + sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */ + return ADV_SUCCESS; + } + slp++; + } + sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; + prev_sg_block = sg_block; + } + while (1); + /* NOTREACHED */ } /* @@ -6719,165 +5532,171 @@ adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, int * * Interrupt callback function for the Narrow SCSI Asc Library. */ -STATIC void -asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) +static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) { - asc_board_t *boardp; - struct scsi_cmnd *scp; - struct Scsi_Host *shp; - int i; - - ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n", - (ulong) asc_dvc_varp, (ulong) qdonep); - ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); + asc_board_t *boardp; + struct scsi_cmnd *scp; + struct Scsi_Host *shost; + int i; + + ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n", + (ulong)asc_dvc_varp, (ulong)qdonep); + ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); + + /* + * Get the struct scsi_cmnd structure and Scsi_Host structure for the + * command that has been completed. + */ + scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr); + ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp); + + if (scp == NULL) { + ASC_PRINT("asc_isr_callback: scp is NULL\n"); + return; + } + ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + + /* + * If the request's host pointer is not valid, display a + * message and return. + */ + shost = scp->device->host; + for (i = 0; i < asc_board_count; i++) { + if (asc_host[i] == shost) { + break; + } + } + if (i == asc_board_count) { + ASC_PRINT2 + ("asc_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", + (ulong)scp, (ulong)shost); + return; + } - /* - * Get the struct scsi_cmnd structure and Scsi_Host structure for the - * command that has been completed. - */ - scp = (struct scsi_cmnd *) ASC_U32_TO_VADDR(qdonep->d2.srb_ptr); - ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong) scp); - - if (scp == NULL) { - ASC_PRINT("asc_isr_callback: scp is NULL\n"); - return; - } - ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + ASC_STATS(shost, callback); + ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost); + + /* + * If the request isn't found on the active queue, it may + * have been removed to handle a reset request. + * Display a message and return. + */ + boardp = ASC_BOARDP(shost); + ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var); + if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { + ASC_PRINT2 + ("asc_isr_callback: board %d: scp 0x%lx not on active queue\n", + boardp->id, (ulong)scp); + return; + } - /* - * If the request's host pointer is not valid, display a - * message and return. - */ - shp = scp->device->host; - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i] == shp) { - break; - } - } - if (i == asc_board_count) { - ASC_PRINT2( - "asc_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", - (ulong) scp, (ulong) shp); - return; - } + /* + * 'qdonep' contains the command's ending status. + */ + switch (qdonep->d3.done_stat) { + case QD_NO_ERROR: + ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); + scp->result = 0; - ASC_STATS(shp, callback); - ASC_DBG1(1, "asc_isr_callback: shp 0x%lx\n", (ulong) shp); + /* + * If an INQUIRY command completed successfully, then call + * the AscInquiryHandling() function to set-up the device. + */ + if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 && + (scp->request_bufflen - qdonep->remain_bytes) >= 8) { + AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7, + (ASC_SCSI_INQUIRY *)scp-> + request_buffer); + } - /* - * If the request isn't found on the active queue, it may - * have been removed to handle a reset request. - * Display a message and return. - */ - boardp = ASC_BOARDP(shp); - ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var); - if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { - ASC_PRINT2( - "asc_isr_callback: board %d: scp 0x%lx not on active queue\n", - boardp->id, (ulong) scp); - return; - } + /* + * Check for an underrun condition. + * + * If there was no error and an underrun condition, then + * then return the number of underrun bytes. + */ + if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && + qdonep->remain_bytes <= scp->request_bufflen) { + ASC_DBG1(1, + "asc_isr_callback: underrun condition %u bytes\n", + (unsigned)qdonep->remain_bytes); + scp->resid = qdonep->remain_bytes; + } + break; + + case QD_WITH_ERROR: + ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); + switch (qdonep->d3.host_stat) { + case QHSTA_NO_ERROR: + if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) { + ASC_DBG(2, + "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n"); + ASC_DBG_PRT_SENSE(2, scp->sense_buffer, + sizeof(scp->sense_buffer)); + /* + * Note: The 'status_byte()' macro used by target drivers + * defined in scsi.h shifts the status byte returned by + * host drivers right by 1 bit. This is why target drivers + * also use right shifted status byte definitions. For + * instance target drivers use CHECK_CONDITION, defined to + * 0x1, instead of the SCSI defined check condition value + * of 0x2. Host drivers are supposed to return the status + * byte as it is defined by SCSI. + */ + scp->result = DRIVER_BYTE(DRIVER_SENSE) | + STATUS_BYTE(qdonep->d3.scsi_stat); + } else { + scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); + } + break; + + default: + /* QHSTA error occurred */ + ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n", + qdonep->d3.host_stat); + scp->result = HOST_BYTE(DID_BAD_TARGET); + break; + } + break; + + case QD_ABORTED_BY_HOST: + ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); + scp->result = + HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3. + scsi_msg) | + STATUS_BYTE(qdonep->d3.scsi_stat); + break; + + default: + ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n", + qdonep->d3.done_stat); + scp->result = + HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3. + scsi_msg) | + STATUS_BYTE(qdonep->d3.scsi_stat); + break; + } - /* - * 'qdonep' contains the command's ending status. - */ - switch (qdonep->d3.done_stat) { - case QD_NO_ERROR: - ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); - scp->result = 0; - - /* - * If an INQUIRY command completed successfully, then call - * the AscInquiryHandling() function to set-up the device. - */ - if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 && - (scp->request_bufflen - qdonep->remain_bytes) >= 8) - { - AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7, - (ASC_SCSI_INQUIRY *) scp->request_buffer); - } - - /* - * Check for an underrun condition. - * - * If there was no error and an underrun condition, then - * then return the number of underrun bytes. - */ - if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && - qdonep->remain_bytes <= scp->request_bufflen) { - ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n", - (unsigned) qdonep->remain_bytes); - scp->resid = qdonep->remain_bytes; - } - break; - - case QD_WITH_ERROR: - ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); - switch (qdonep->d3.host_stat) { - case QHSTA_NO_ERROR: - if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) { - ASC_DBG(2, "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n"); - ASC_DBG_PRT_SENSE(2, scp->sense_buffer, - sizeof(scp->sense_buffer)); - /* - * Note: The 'status_byte()' macro used by target drivers - * defined in scsi.h shifts the status byte returned by - * host drivers right by 1 bit. This is why target drivers - * also use right shifted status byte definitions. For - * instance target drivers use CHECK_CONDITION, defined to - * 0x1, instead of the SCSI defined check condition value - * of 0x2. Host drivers are supposed to return the status - * byte as it is defined by SCSI. - */ - scp->result = DRIVER_BYTE(DRIVER_SENSE) | - STATUS_BYTE(qdonep->d3.scsi_stat); - } else { - scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); - } - break; - - default: - /* QHSTA error occurred */ - ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n", - qdonep->d3.host_stat); - scp->result = HOST_BYTE(DID_BAD_TARGET); - break; - } - break; - - case QD_ABORTED_BY_HOST: - ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); - scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); - break; - - default: - ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n", qdonep->d3.done_stat); - scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); - break; - } + /* + * If the 'init_tidmask' bit isn't already set for the target and the + * current request finished normally, then set the bit for the target + * to indicate that a device is present. + */ + if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && + qdonep->d3.done_stat == QD_NO_ERROR && + qdonep->d3.host_stat == QHSTA_NO_ERROR) { + boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); + } - /* - * If the 'init_tidmask' bit isn't already set for the target and the - * current request finished normally, then set the bit for the target - * to indicate that a device is present. - */ - if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && - qdonep->d3.done_stat == QD_NO_ERROR && - qdonep->d3.host_stat == QHSTA_NO_ERROR) { - boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); - } + /* + * Because interrupts may be enabled by the 'struct scsi_cmnd' done + * function, add the command to the end of the board's done queue. + * The done function for the command will be called from + * advansys_interrupt(). + */ + asc_enqueue(&boardp->done, scp, ASC_BACK); - /* - * Because interrupts may be enabled by the 'struct scsi_cmnd' done - * function, add the command to the end of the board's done queue. - * The done function for the command will be called from - * advansys_interrupt(). - */ - asc_enqueue(&boardp->done, scp, ASC_BACK); - - return; + return; } /* @@ -6885,238 +5704,240 @@ asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) * * Callback function for the Wide SCSI Adv Library. */ -STATIC void -adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) +static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) { - asc_board_t *boardp; - adv_req_t *reqp; - adv_sgblk_t *sgblkp; - struct scsi_cmnd *scp; - struct Scsi_Host *shp; - int i; - ADV_DCNT resid_cnt; - - - ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n", - (ulong) adv_dvc_varp, (ulong) scsiqp); - ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); - - /* - * Get the adv_req_t structure for the command that has been - * completed. The adv_req_t structure actually contains the - * completed ADV_SCSI_REQ_Q structure. - */ - reqp = (adv_req_t *) ADV_U32_TO_VADDR(scsiqp->srb_ptr); - ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong) reqp); - if (reqp == NULL) { - ASC_PRINT("adv_isr_callback: reqp is NULL\n"); - return; - } - - /* - * Get the struct scsi_cmnd structure and Scsi_Host structure for the - * command that has been completed. - * - * Note: The adv_req_t request structure and adv_sgblk_t structure, - * if any, are dropped, because a board structure pointer can not be - * determined. - */ - scp = reqp->cmndp; - ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong) scp); - if (scp == NULL) { - ASC_PRINT("adv_isr_callback: scp is NULL; adv_req_t dropped.\n"); - return; - } - ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); - - /* - * If the request's host pointer is not valid, display a message - * and return. - */ - shp = scp->device->host; - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i] == shp) { - break; - } - } - /* - * Note: If the host structure is not found, the adv_req_t request - * structure and adv_sgblk_t structure, if any, is dropped. - */ - if (i == asc_board_count) { - ASC_PRINT2( - "adv_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", - (ulong) scp, (ulong) shp); - return; - } + asc_board_t *boardp; + adv_req_t *reqp; + adv_sgblk_t *sgblkp; + struct scsi_cmnd *scp; + struct Scsi_Host *shost; + int i; + ADV_DCNT resid_cnt; + + ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n", + (ulong)adv_dvc_varp, (ulong)scsiqp); + ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); + + /* + * Get the adv_req_t structure for the command that has been + * completed. The adv_req_t structure actually contains the + * completed ADV_SCSI_REQ_Q structure. + */ + reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr); + ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp); + if (reqp == NULL) { + ASC_PRINT("adv_isr_callback: reqp is NULL\n"); + return; + } - ASC_STATS(shp, callback); - ASC_DBG1(1, "adv_isr_callback: shp 0x%lx\n", (ulong) shp); + /* + * Get the struct scsi_cmnd structure and Scsi_Host structure for the + * command that has been completed. + * + * Note: The adv_req_t request structure and adv_sgblk_t structure, + * if any, are dropped, because a board structure pointer can not be + * determined. + */ + scp = reqp->cmndp; + ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp); + if (scp == NULL) { + ASC_PRINT + ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n"); + return; + } + ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + + /* + * If the request's host pointer is not valid, display a message + * and return. + */ + shost = scp->device->host; + for (i = 0; i < asc_board_count; i++) { + if (asc_host[i] == shost) { + break; + } + } + /* + * Note: If the host structure is not found, the adv_req_t request + * structure and adv_sgblk_t structure, if any, is dropped. + */ + if (i == asc_board_count) { + ASC_PRINT2 + ("adv_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", + (ulong)scp, (ulong)shost); + return; + } - /* - * If the request isn't found on the active queue, it may have been - * removed to handle a reset request. Display a message and return. - * - * Note: Because the structure may still be in use don't attempt - * to free the adv_req_t and adv_sgblk_t, if any, structures. - */ - boardp = ASC_BOARDP(shp); - ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var); - if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { - ASC_PRINT2( - "adv_isr_callback: board %d: scp 0x%lx not on active queue\n", - boardp->id, (ulong) scp); - return; - } + ASC_STATS(shost, callback); + ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost); + + /* + * If the request isn't found on the active queue, it may have been + * removed to handle a reset request. Display a message and return. + * + * Note: Because the structure may still be in use don't attempt + * to free the adv_req_t and adv_sgblk_t, if any, structures. + */ + boardp = ASC_BOARDP(shost); + ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var); + if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { + ASC_PRINT2 + ("adv_isr_callback: board %d: scp 0x%lx not on active queue\n", + boardp->id, (ulong)scp); + return; + } - /* - * 'done_status' contains the command's ending status. - */ - switch (scsiqp->done_status) { - case QD_NO_ERROR: - ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n"); - scp->result = 0; - - /* - * Check for an underrun condition. - * - * If there was no error and an underrun condition, then - * then return the number of underrun bytes. - */ - resid_cnt = le32_to_cpu(scsiqp->data_cnt); - if (scp->request_bufflen != 0 && resid_cnt != 0 && - resid_cnt <= scp->request_bufflen) { - ASC_DBG1(1, "adv_isr_callback: underrun condition %lu bytes\n", - (ulong) resid_cnt); - scp->resid = resid_cnt; - } - break; - - case QD_WITH_ERROR: - ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n"); - switch (scsiqp->host_status) { - case QHSTA_NO_ERROR: - if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) { - ASC_DBG(2, "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n"); - ASC_DBG_PRT_SENSE(2, scp->sense_buffer, - sizeof(scp->sense_buffer)); - /* - * Note: The 'status_byte()' macro used by target drivers - * defined in scsi.h shifts the status byte returned by - * host drivers right by 1 bit. This is why target drivers - * also use right shifted status byte definitions. For - * instance target drivers use CHECK_CONDITION, defined to - * 0x1, instead of the SCSI defined check condition value - * of 0x2. Host drivers are supposed to return the status - * byte as it is defined by SCSI. - */ - scp->result = DRIVER_BYTE(DRIVER_SENSE) | - STATUS_BYTE(scsiqp->scsi_status); - } else { - scp->result = STATUS_BYTE(scsiqp->scsi_status); - } - break; - - default: - /* Some other QHSTA error occurred. */ - ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n", - scsiqp->host_status); - scp->result = HOST_BYTE(DID_BAD_TARGET); - break; - } - break; - - case QD_ABORTED_BY_HOST: - ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n"); - scp->result = HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status); - break; - - default: - ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n", scsiqp->done_status); - scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); - break; - } + /* + * 'done_status' contains the command's ending status. + */ + switch (scsiqp->done_status) { + case QD_NO_ERROR: + ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n"); + scp->result = 0; - /* - * If the 'init_tidmask' bit isn't already set for the target and the - * current request finished normally, then set the bit for the target - * to indicate that a device is present. - */ - if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && - scsiqp->done_status == QD_NO_ERROR && - scsiqp->host_status == QHSTA_NO_ERROR) { - boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); - } + /* + * Check for an underrun condition. + * + * If there was no error and an underrun condition, then + * then return the number of underrun bytes. + */ + resid_cnt = le32_to_cpu(scsiqp->data_cnt); + if (scp->request_bufflen != 0 && resid_cnt != 0 && + resid_cnt <= scp->request_bufflen) { + ASC_DBG1(1, + "adv_isr_callback: underrun condition %lu bytes\n", + (ulong)resid_cnt); + scp->resid = resid_cnt; + } + break; + + case QD_WITH_ERROR: + ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n"); + switch (scsiqp->host_status) { + case QHSTA_NO_ERROR: + if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) { + ASC_DBG(2, + "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n"); + ASC_DBG_PRT_SENSE(2, scp->sense_buffer, + sizeof(scp->sense_buffer)); + /* + * Note: The 'status_byte()' macro used by target drivers + * defined in scsi.h shifts the status byte returned by + * host drivers right by 1 bit. This is why target drivers + * also use right shifted status byte definitions. For + * instance target drivers use CHECK_CONDITION, defined to + * 0x1, instead of the SCSI defined check condition value + * of 0x2. Host drivers are supposed to return the status + * byte as it is defined by SCSI. + */ + scp->result = DRIVER_BYTE(DRIVER_SENSE) | + STATUS_BYTE(scsiqp->scsi_status); + } else { + scp->result = STATUS_BYTE(scsiqp->scsi_status); + } + break; + + default: + /* Some other QHSTA error occurred. */ + ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n", + scsiqp->host_status); + scp->result = HOST_BYTE(DID_BAD_TARGET); + break; + } + break; + + case QD_ABORTED_BY_HOST: + ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n"); + scp->result = + HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status); + break; + + default: + ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n", + scsiqp->done_status); + scp->result = + HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); + break; + } - /* - * Because interrupts may be enabled by the 'struct scsi_cmnd' done - * function, add the command to the end of the board's done queue. - * The done function for the command will be called from - * advansys_interrupt(). - */ - asc_enqueue(&boardp->done, scp, ASC_BACK); + /* + * If the 'init_tidmask' bit isn't already set for the target and the + * current request finished normally, then set the bit for the target + * to indicate that a device is present. + */ + if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && + scsiqp->done_status == QD_NO_ERROR && + scsiqp->host_status == QHSTA_NO_ERROR) { + boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); + } - /* - * Free all 'adv_sgblk_t' structures allocated for the request. - */ - while ((sgblkp = reqp->sgblkp) != NULL) - { - /* Remove 'sgblkp' from the request list. */ - reqp->sgblkp = sgblkp->next_sgblkp; - - /* Add 'sgblkp' to the board free list. */ - sgblkp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgblkp; - } + /* + * Because interrupts may be enabled by the 'struct scsi_cmnd' done + * function, add the command to the end of the board's done queue. + * The done function for the command will be called from + * advansys_interrupt(). + */ + asc_enqueue(&boardp->done, scp, ASC_BACK); + + /* + * Free all 'adv_sgblk_t' structures allocated for the request. + */ + while ((sgblkp = reqp->sgblkp) != NULL) { + /* Remove 'sgblkp' from the request list. */ + reqp->sgblkp = sgblkp->next_sgblkp; + + /* Add 'sgblkp' to the board free list. */ + sgblkp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgblkp; + } - /* - * Free the adv_req_t structure used with the command by adding - * it back to the board free list. - */ - reqp->next_reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp; + /* + * Free the adv_req_t structure used with the command by adding + * it back to the board free list. + */ + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; - ASC_DBG(1, "adv_isr_callback: done\n"); + ASC_DBG(1, "adv_isr_callback: done\n"); - return; + return; } /* * adv_async_callback() - Adv Library asynchronous event callback function. */ -STATIC void -adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) +static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) { - switch (code) - { - case ADV_ASYNC_SCSI_BUS_RESET_DET: - /* - * The firmware detected a SCSI Bus reset. - */ - ASC_DBG(0, "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n"); - break; - - case ADV_ASYNC_RDMA_FAILURE: - /* - * Handle RDMA failure by resetting the SCSI Bus and - * possibly the chip if it is unresponsive. Log the error - * with a unique code. - */ - ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n"); - AdvResetChipAndSB(adv_dvc_varp); - break; - - case ADV_HOST_SCSI_BUS_RESET: - /* - * Host generated SCSI bus reset occurred. - */ - ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n"); - break; - - default: - ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code); - break; - } + switch (code) { + case ADV_ASYNC_SCSI_BUS_RESET_DET: + /* + * The firmware detected a SCSI Bus reset. + */ + ASC_DBG(0, + "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n"); + break; + + case ADV_ASYNC_RDMA_FAILURE: + /* + * Handle RDMA failure by resetting the SCSI Bus and + * possibly the chip if it is unresponsive. Log the error + * with a unique code. + */ + ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n"); + AdvResetChipAndSB(adv_dvc_varp); + break; + + case ADV_HOST_SCSI_BUS_RESET: + /* + * Host generated SCSI bus reset occurred. + */ + ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n"); + break; + + default: + ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code); + break; + } } /* @@ -7127,50 +5948,50 @@ adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) * * 'REQPNEXT(reqp)' returns reqp's next pointer. */ -STATIC void -asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag) +static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag) { - int tid; - - ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n", - (ulong) ascq, (ulong) reqp, flag); - ASC_ASSERT(reqp != NULL); - ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK); - tid = REQPTID(reqp); - ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - if (flag == ASC_FRONT) { - reqp->host_scribble = (unsigned char *)ascq->q_first[tid]; - ascq->q_first[tid] = reqp; - /* If the queue was empty, set the last pointer. */ - if (ascq->q_last[tid] == NULL) { - ascq->q_last[tid] = reqp; - } - } else { /* ASC_BACK */ - if (ascq->q_last[tid] != NULL) { - ascq->q_last[tid]->host_scribble = (unsigned char *)reqp; - } - ascq->q_last[tid] = reqp; - reqp->host_scribble = NULL; - /* If the queue was empty, set the first pointer. */ - if (ascq->q_first[tid] == NULL) { - ascq->q_first[tid] = reqp; - } - } - /* The queue has at least one entry, set its bit. */ - ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid); + int tid; + + ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n", + (ulong)ascq, (ulong)reqp, flag); + ASC_ASSERT(reqp != NULL); + ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK); + tid = REQPTID(reqp); + ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); + if (flag == ASC_FRONT) { + reqp->host_scribble = (unsigned char *)ascq->q_first[tid]; + ascq->q_first[tid] = reqp; + /* If the queue was empty, set the last pointer. */ + if (ascq->q_last[tid] == NULL) { + ascq->q_last[tid] = reqp; + } + } else { /* ASC_BACK */ + if (ascq->q_last[tid] != NULL) { + ascq->q_last[tid]->host_scribble = + (unsigned char *)reqp; + } + ascq->q_last[tid] = reqp; + reqp->host_scribble = NULL; + /* If the queue was empty, set the first pointer. */ + if (ascq->q_first[tid] == NULL) { + ascq->q_first[tid] = reqp; + } + } + /* The queue has at least one entry, set its bit. */ + ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid); #ifdef ADVANSYS_STATS - /* Maintain request queue statistics. */ - ascq->q_tot_cnt[tid]++; - ascq->q_cur_cnt[tid]++; - if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) { - ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid]; - ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n", - tid, ascq->q_max_cnt[tid]); - } - REQPTIME(reqp) = REQTIMESTAMP(); + /* Maintain request queue statistics. */ + ascq->q_tot_cnt[tid]++; + ascq->q_cur_cnt[tid]++; + if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) { + ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid]; + ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n", + tid, ascq->q_max_cnt[tid]); + } + REQPTIME(reqp) = REQTIMESTAMP(); #endif /* ADVANSYS_STATS */ - ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong) reqp); - return; + ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong)reqp); + return; } /* @@ -7180,31 +6001,30 @@ asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag) * * 'REQPNEXT(reqp)' returns reqp's next pointer. */ -STATIC REQP -asc_dequeue(asc_queue_t *ascq, int tid) +static REQP asc_dequeue(asc_queue_t *ascq, int tid) { - REQP reqp; - - ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong) ascq, tid); - ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - if ((reqp = ascq->q_first[tid]) != NULL) { - ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)); - ascq->q_first[tid] = REQPNEXT(reqp); - /* If the queue is empty, clear its bit and the last pointer. */ - if (ascq->q_first[tid] == NULL) { - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); - ASC_ASSERT(ascq->q_last[tid] == reqp); - ascq->q_last[tid] = NULL; - } + REQP reqp; + + ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong)ascq, tid); + ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); + if ((reqp = ascq->q_first[tid]) != NULL) { + ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)); + ascq->q_first[tid] = REQPNEXT(reqp); + /* If the queue is empty, clear its bit and the last pointer. */ + if (ascq->q_first[tid] == NULL) { + ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); + ASC_ASSERT(ascq->q_last[tid] == reqp); + ascq->q_last[tid] = NULL; + } #ifdef ADVANSYS_STATS - /* Maintain request queue statistics. */ - ascq->q_cur_cnt[tid]--; - ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); - REQTIMESTAT("asc_dequeue", ascq, reqp, tid); + /* Maintain request queue statistics. */ + ascq->q_cur_cnt[tid]--; + ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); + REQTIMESTAT("asc_dequeue", ascq, reqp, tid); #endif /* ADVANSYS_STATS */ - } - ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong) reqp); - return reqp; + } + ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong)reqp); + return reqp; } /* @@ -7227,74 +6047,76 @@ asc_dequeue(asc_queue_t *ascq, int tid) * Unfortunately collecting queuing time statistics adds overhead to * the function that isn't inherent to the function's algorithm. */ -STATIC REQP -asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) +static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) { - REQP firstp, lastp; - int i; - - ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong) ascq, tid); - ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID)); - - /* - * If 'tid' is not ASC_TID_ALL, return requests only for - * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all - * requests for all tids. - */ - if (tid != ASC_TID_ALL) { - /* Return all requests for the specified 'tid'. */ - if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) { - /* List is empty; Set first and last return pointers to NULL. */ - firstp = lastp = NULL; - } else { - firstp = ascq->q_first[tid]; - lastp = ascq->q_last[tid]; - ascq->q_first[tid] = ascq->q_last[tid] = NULL; - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); + REQP firstp, lastp; + int i; + + ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong)ascq, tid); + ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID)); + + /* + * If 'tid' is not ASC_TID_ALL, return requests only for + * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all + * requests for all tids. + */ + if (tid != ASC_TID_ALL) { + /* Return all requests for the specified 'tid'. */ + if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) { + /* List is empty; Set first and last return pointers to NULL. */ + firstp = lastp = NULL; + } else { + firstp = ascq->q_first[tid]; + lastp = ascq->q_last[tid]; + ascq->q_first[tid] = ascq->q_last[tid] = NULL; + ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); #ifdef ADVANSYS_STATS - { - REQP reqp; - ascq->q_cur_cnt[tid] = 0; - for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { - REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid); - } - } + { + REQP reqp; + ascq->q_cur_cnt[tid] = 0; + for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { + REQTIMESTAT("asc_dequeue_list", ascq, + reqp, tid); + } + } #endif /* ADVANSYS_STATS */ - } - } else { - /* Return all requests for all tids. */ - firstp = lastp = NULL; - for (i = 0; i <= ADV_MAX_TID; i++) { - if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) { - if (firstp == NULL) { - firstp = ascq->q_first[i]; - lastp = ascq->q_last[i]; - } else { - ASC_ASSERT(lastp != NULL); - lastp->host_scribble = (unsigned char *)ascq->q_first[i]; - lastp = ascq->q_last[i]; - } - ascq->q_first[i] = ascq->q_last[i] = NULL; - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i); + } + } else { + /* Return all requests for all tids. */ + firstp = lastp = NULL; + for (i = 0; i <= ADV_MAX_TID; i++) { + if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) { + if (firstp == NULL) { + firstp = ascq->q_first[i]; + lastp = ascq->q_last[i]; + } else { + ASC_ASSERT(lastp != NULL); + lastp->host_scribble = + (unsigned char *)ascq->q_first[i]; + lastp = ascq->q_last[i]; + } + ascq->q_first[i] = ascq->q_last[i] = NULL; + ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i); #ifdef ADVANSYS_STATS - ascq->q_cur_cnt[i] = 0; + ascq->q_cur_cnt[i] = 0; #endif /* ADVANSYS_STATS */ - } - } + } + } #ifdef ADVANSYS_STATS - { - REQP reqp; - for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { - REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->device->id); - } - } + { + REQP reqp; + for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { + REQTIMESTAT("asc_dequeue_list", ascq, reqp, + reqp->device->id); + } + } #endif /* ADVANSYS_STATS */ - } - if (lastpp) { - *lastpp = lastp; - } - ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong) firstp); - return firstp; + } + if (lastpp) { + *lastpp = lastp; + } + ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp); + return firstp; } /* @@ -7307,67 +6129,67 @@ asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) * Return ASC_TRUE if the command was found and removed, * otherwise return ASC_FALSE. */ -STATIC int -asc_rmqueue(asc_queue_t *ascq, REQP reqp) +static int asc_rmqueue(asc_queue_t *ascq, REQP reqp) { - REQP currp, prevp; - int tid; - int ret = ASC_FALSE; - - ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n", - (ulong) ascq, (ulong) reqp); - ASC_ASSERT(reqp != NULL); - - tid = REQPTID(reqp); - ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - - /* - * Handle the common case of 'reqp' being the first - * entry on the queue. - */ - if (reqp == ascq->q_first[tid]) { - ret = ASC_TRUE; - ascq->q_first[tid] = REQPNEXT(reqp); - /* If the queue is now empty, clear its bit and the last pointer. */ - if (ascq->q_first[tid] == NULL) { - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); - ASC_ASSERT(ascq->q_last[tid] == reqp); - ascq->q_last[tid] = NULL; - } - } else if (ascq->q_first[tid] != NULL) { - ASC_ASSERT(ascq->q_last[tid] != NULL); - /* - * Because the case of 'reqp' being the first entry has been - * handled above and it is known the queue is not empty, if - * 'reqp' is found on the queue it is guaranteed the queue will - * not become empty and that 'q_first[tid]' will not be changed. - * - * Set 'prevp' to the first entry, 'currp' to the second entry, - * and search for 'reqp'. - */ - for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp); - currp; prevp = currp, currp = REQPNEXT(currp)) { - if (currp == reqp) { - ret = ASC_TRUE; - prevp->host_scribble = (unsigned char *)REQPNEXT(currp); - reqp->host_scribble = NULL; - if (ascq->q_last[tid] == reqp) { - ascq->q_last[tid] = prevp; - } - break; - } - } - } + REQP currp, prevp; + int tid; + int ret = ASC_FALSE; + + ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n", + (ulong)ascq, (ulong)reqp); + ASC_ASSERT(reqp != NULL); + + tid = REQPTID(reqp); + ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); + + /* + * Handle the common case of 'reqp' being the first + * entry on the queue. + */ + if (reqp == ascq->q_first[tid]) { + ret = ASC_TRUE; + ascq->q_first[tid] = REQPNEXT(reqp); + /* If the queue is now empty, clear its bit and the last pointer. */ + if (ascq->q_first[tid] == NULL) { + ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); + ASC_ASSERT(ascq->q_last[tid] == reqp); + ascq->q_last[tid] = NULL; + } + } else if (ascq->q_first[tid] != NULL) { + ASC_ASSERT(ascq->q_last[tid] != NULL); + /* + * Because the case of 'reqp' being the first entry has been + * handled above and it is known the queue is not empty, if + * 'reqp' is found on the queue it is guaranteed the queue will + * not become empty and that 'q_first[tid]' will not be changed. + * + * Set 'prevp' to the first entry, 'currp' to the second entry, + * and search for 'reqp'. + */ + for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp); + currp; prevp = currp, currp = REQPNEXT(currp)) { + if (currp == reqp) { + ret = ASC_TRUE; + prevp->host_scribble = + (unsigned char *)REQPNEXT(currp); + reqp->host_scribble = NULL; + if (ascq->q_last[tid] == reqp) { + ascq->q_last[tid] = prevp; + } + break; + } + } + } #ifdef ADVANSYS_STATS - /* Maintain request queue statistics. */ - if (ret == ASC_TRUE) { - ascq->q_cur_cnt[tid]--; - REQTIMESTAT("asc_rmqueue", ascq, reqp, tid); - } - ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); + /* Maintain request queue statistics. */ + if (ret == ASC_TRUE) { + ascq->q_cur_cnt[tid]--; + REQTIMESTAT("asc_rmqueue", ascq, reqp, tid); + } + ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); #endif /* ADVANSYS_STATS */ - ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong) reqp, ret); - return ret; + ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong)reqp, ret); + return ret; } /* @@ -7375,37 +6197,38 @@ asc_rmqueue(asc_queue_t *ascq, REQP reqp) * * Calls asc_execute_scsi_cmnd() to execute a REQP/struct scsi_cmnd. */ -STATIC void -asc_execute_queue(asc_queue_t *ascq) +static void asc_execute_queue(asc_queue_t *ascq) { - ADV_SCSI_BIT_ID_TYPE scan_tidmask; - REQP reqp; - int i; - - ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong) ascq); - /* - * Execute queued commands for devices attached to - * the current board in round-robin fashion. - */ - scan_tidmask = ascq->q_tidmask; - do { - for (i = 0; i <= ADV_MAX_TID; i++) { - if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) { - if ((reqp = asc_dequeue(ascq, i)) == NULL) { - scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); - } else if (asc_execute_scsi_cmnd((struct scsi_cmnd *) reqp) - == ASC_BUSY) { - scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); - /* - * The request returned ASC_BUSY. Enqueue at the front of - * target's waiting list to maintain correct ordering. - */ - asc_enqueue(ascq, reqp, ASC_FRONT); - } - } - } - } while (scan_tidmask); - return; + ADV_SCSI_BIT_ID_TYPE scan_tidmask; + REQP reqp; + int i; + + ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong)ascq); + /* + * Execute queued commands for devices attached to + * the current board in round-robin fashion. + */ + scan_tidmask = ascq->q_tidmask; + do { + for (i = 0; i <= ADV_MAX_TID; i++) { + if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) { + if ((reqp = asc_dequeue(ascq, i)) == NULL) { + scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); + } else + if (asc_execute_scsi_cmnd + ((struct scsi_cmnd *)reqp) + == ASC_BUSY) { + scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); + /* + * The request returned ASC_BUSY. Enqueue at the front of + * target's waiting list to maintain correct ordering. + */ + asc_enqueue(ascq, reqp, ASC_FRONT); + } + } + } + } while (scan_tidmask); + return; } #ifdef CONFIG_PROC_FS @@ -7420,102 +6243,102 @@ asc_execute_queue(asc_queue_t *ascq) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int leftlen; - int totlen; - int len; - int chip_scsi_id; - int i; - - boardp = ASC_BOARDP(shp); - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nDevice Information for AdvanSys SCSI Host %d:\n", shp->host_no); - ASC_PRT_NEXT(); - - if (ASC_NARROW_BOARD(boardp)) { - chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; - } else { - chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; - } + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + int chip_scsi_id; + int i; + + boardp = ASC_BOARDP(shost); + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nDevice Information for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + if (ASC_NARROW_BOARD(boardp)) { + chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; + } else { + chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; + } - len = asc_prt_line(cp, leftlen, "Target IDs Detected:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) { - len = asc_prt_line(cp, leftlen, " %X,", i); - ASC_PRT_NEXT(); - } - } - len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, "Target IDs Detected:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) { + len = asc_prt_line(cp, leftlen, " %X,", i); + ASC_PRT_NEXT(); + } + } + len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id); + ASC_PRT_NEXT(); - return totlen; + return totlen; } /* * Display Wide Board BIOS Information. */ -STATIC int -asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int leftlen; - int totlen; - int len; - ushort major, minor, letter; - - boardp = ASC_BOARDP(shp); - leftlen = cplen; - totlen = len = 0; + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + ushort major, minor, letter; + + boardp = ASC_BOARDP(shost); + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: "); + ASC_PRT_NEXT(); + + /* + * If the BIOS saved a valid signature, then fill in + * the BIOS code segment base address. + */ + if (boardp->bios_signature != 0x55AA) { + len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n"); + ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n"); + ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n"); + ASC_PRT_NEXT(); + } else { + major = (boardp->bios_version >> 12) & 0xF; + minor = (boardp->bios_version >> 8) & 0xF; + letter = (boardp->bios_version & 0xFF); - len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: "); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, "%d.%d%c\n", + major, minor, + letter >= 26 ? '?' : letter + 'A'); + ASC_PRT_NEXT(); - /* - * If the BIOS saved a valid signature, then fill in - * the BIOS code segment base address. - */ - if (boardp->bios_signature != 0x55AA) { - len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n"); - ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, -"BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n"); - ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, -"can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n"); - ASC_PRT_NEXT(); - } else { - major = (boardp->bios_version >> 12) & 0xF; - minor = (boardp->bios_version >> 8) & 0xF; - letter = (boardp->bios_version & 0xFF); - - len = asc_prt_line(cp, leftlen, "%d.%d%c\n", - major, minor, letter >= 26 ? '?' : letter + 'A'); - ASC_PRT_NEXT(); - - /* - * Current available ROM BIOS release is 3.1I for UW - * and 3.2I for U2W. This code doesn't differentiate - * UW and U2W boards. - */ - if (major < 3 || (major <= 3 && minor < 1) || - (major <= 3 && minor <= 1 && letter < ('I'- 'A'))) { - len = asc_prt_line(cp, leftlen, -"Newer version of ROM BIOS is available at the ConnectCom FTP site:\n"); - ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, -"ftp://ftp.connectcom.net/pub\n"); - ASC_PRT_NEXT(); - } - } + /* + * Current available ROM BIOS release is 3.1I for UW + * and 3.2I for U2W. This code doesn't differentiate + * UW and U2W boards. + */ + if (major < 3 || (major <= 3 && minor < 1) || + (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) { + len = asc_prt_line(cp, leftlen, + "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n"); + ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + "ftp://ftp.connectcom.net/pub\n"); + ASC_PRT_NEXT(); + } + } - return totlen; + return totlen; } /* @@ -7541,80 +6364,79 @@ asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen) * * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE. */ -STATIC int -asc_get_eeprom_string(ushort *serialnum, uchar *cp) +static int asc_get_eeprom_string(ushort *serialnum, uchar *cp) { - ushort w, num; - - if ((serialnum[1] & 0xFE00) != ((ushort) 0xAA << 8)) { - return ASC_FALSE; - } else { - /* - * First word - 6 digits. - */ - w = serialnum[0]; - - /* Product type - 1st digit. */ - if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') { - /* Product type is P=Prototype */ - *cp += 0x8; - } - cp++; - - /* Manufacturing location - 2nd digit. */ - *cp++ = 'A' + ((w & 0x1C00) >> 10); - - /* Product ID - 3rd, 4th digits. */ - num = w & 0x3FF; - *cp++ = '0' + (num / 100); - num %= 100; - *cp++ = '0' + (num / 10); - - /* Product revision - 5th digit. */ - *cp++ = 'A' + (num % 10); - - /* - * Second word - */ - w = serialnum[1]; - - /* - * Year - 6th digit. - * - * If bit 15 of third word is set, then the - * last digit of the year is greater than 7. - */ - if (serialnum[2] & 0x8000) { - *cp++ = '8' + ((w & 0x1C0) >> 6); - } else { - *cp++ = '0' + ((w & 0x1C0) >> 6); - } - - /* Week of year - 7th, 8th digits. */ - num = w & 0x003F; - *cp++ = '0' + num / 10; - num %= 10; - *cp++ = '0' + num; - - /* - * Third word - */ - w = serialnum[2] & 0x7FFF; - - /* Serial number - 9th digit. */ - *cp++ = 'A' + (w / 1000); - - /* 10th, 11th, 12th digits. */ - num = w % 1000; - *cp++ = '0' + num / 100; - num %= 100; - *cp++ = '0' + num / 10; - num %= 10; - *cp++ = '0' + num; - - *cp = '\0'; /* Null Terminate the string. */ - return ASC_TRUE; - } + ushort w, num; + + if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) { + return ASC_FALSE; + } else { + /* + * First word - 6 digits. + */ + w = serialnum[0]; + + /* Product type - 1st digit. */ + if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') { + /* Product type is P=Prototype */ + *cp += 0x8; + } + cp++; + + /* Manufacturing location - 2nd digit. */ + *cp++ = 'A' + ((w & 0x1C00) >> 10); + + /* Product ID - 3rd, 4th digits. */ + num = w & 0x3FF; + *cp++ = '0' + (num / 100); + num %= 100; + *cp++ = '0' + (num / 10); + + /* Product revision - 5th digit. */ + *cp++ = 'A' + (num % 10); + + /* + * Second word + */ + w = serialnum[1]; + + /* + * Year - 6th digit. + * + * If bit 15 of third word is set, then the + * last digit of the year is greater than 7. + */ + if (serialnum[2] & 0x8000) { + *cp++ = '8' + ((w & 0x1C0) >> 6); + } else { + *cp++ = '0' + ((w & 0x1C0) >> 6); + } + + /* Week of year - 7th, 8th digits. */ + num = w & 0x003F; + *cp++ = '0' + num / 10; + num %= 10; + *cp++ = '0' + num; + + /* + * Third word + */ + w = serialnum[2] & 0x7FFF; + + /* Serial number - 9th digit. */ + *cp++ = 'A' + (w / 1000); + + /* 10th, 11th, 12th digits. */ + num = w % 1000; + *cp++ = '0' + num / 100; + num %= 100; + *cp++ = '0' + num / 10; + num %= 10; + *cp++ = '0' + num; + + *cp = '\0'; /* Null Terminate the string. */ + return ASC_TRUE; + } } /* @@ -7628,122 +6450,127 @@ asc_get_eeprom_string(ushort *serialnum, uchar *cp) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - int leftlen; - int totlen; - int len; - ASCEEP_CONFIG *ep; - int i; + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; + int leftlen; + int totlen; + int len; + ASCEEP_CONFIG *ep; + int i; #ifdef CONFIG_ISA - int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 }; + int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 }; #endif /* CONFIG_ISA */ - uchar serialstr[13]; - - boardp = ASC_BOARDP(shp); - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - ep = &boardp->eep_config.asc_eep; - - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no); - ASC_PRT_NEXT(); - - if (asc_get_eeprom_string((ushort *) &ep->adapter_info[0], serialstr) == - ASC_TRUE) { - len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr); - ASC_PRT_NEXT(); - } else { - if (ep->adapter_info[5] == 0xBB) { - len = asc_prt_line(cp, leftlen, - " Default Settings Used for EEPROM-less Adapter.\n"); - ASC_PRT_NEXT(); - } else { - len = asc_prt_line(cp, leftlen, - " Serial Number Signature Not Present.\n"); - ASC_PRT_NEXT(); - } - } + uchar serialstr[13]; + + boardp = ASC_BOARDP(shost); + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + ep = &boardp->eep_config.asc_eep; + + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr) + == ASC_TRUE) { + len = + asc_prt_line(cp, leftlen, " Serial Number: %s\n", + serialstr); + ASC_PRT_NEXT(); + } else { + if (ep->adapter_info[5] == 0xBB) { + len = asc_prt_line(cp, leftlen, + " Default Settings Used for EEPROM-less Adapter.\n"); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " Serial Number Signature Not Present.\n"); + ASC_PRT_NEXT(); + } + } - len = asc_prt_line(cp, leftlen, -" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng, ep->max_tag_qng); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" cntl 0x%x, no_scam 0x%x\n", - ep->cntl, ep->no_scam); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Target ID: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %d", i); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Disconnects: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Command Queuing: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Start Motor: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Synchronous Transfer:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng, + ep->max_tag_qng); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Target ID: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %d", i); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Disconnects: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Command Queuing: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Start Motor: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); #ifdef CONFIG_ISA - if (asc_dvc_varp->bus_type & ASC_IS_ISA) { - len = asc_prt_line(cp, leftlen, -" Host ISA DMA speed: %d MB/S\n", - isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]); - ASC_PRT_NEXT(); - } + if (asc_dvc_varp->bus_type & ASC_IS_ISA) { + len = asc_prt_line(cp, leftlen, + " Host ISA DMA speed: %d MB/S\n", + isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]); + ASC_PRT_NEXT(); + } #endif /* CONFIG_ISA */ - return totlen; + return totlen; } /* @@ -7757,300 +6584,282 @@ asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - ADV_DVC_VAR *adv_dvc_varp; - int leftlen; - int totlen; - int len; - int i; - char *termstr; - uchar serialstr[13]; - ADVEEP_3550_CONFIG *ep_3550 = NULL; - ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL; - ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL; - ushort word; - ushort *wordp; - ushort sdtr_speed = 0; - - boardp = ASC_BOARDP(shp); - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - ep_3550 = &boardp->eep_config.adv_3550_eep; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; - } else - { - ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; - } + asc_board_t *boardp; + ADV_DVC_VAR *adv_dvc_varp; + int leftlen; + int totlen; + int len; + int i; + char *termstr; + uchar serialstr[13]; + ADVEEP_3550_CONFIG *ep_3550 = NULL; + ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL; + ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL; + ushort word; + ushort *wordp; + ushort sdtr_speed = 0; + + boardp = ASC_BOARDP(shost); + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + ep_3550 = &boardp->eep_config.adv_3550_eep; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; + } else { + ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; + } - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - wordp = &ep_3550->serial_number_word1; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - wordp = &ep_38C0800->serial_number_word1; - } else - { - wordp = &ep_38C1600->serial_number_word1; - } + leftlen = cplen; + totlen = len = 0; - if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) { - len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr); - ASC_PRT_NEXT(); - } else { - len = asc_prt_line(cp, leftlen, - " Serial Number Signature Not Present.\n"); - ASC_PRT_NEXT(); - } + len = asc_prt_line(cp, leftlen, + "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - len = asc_prt_line(cp, leftlen, -" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ep_3550->adapter_scsi_id, ep_3550->max_host_qng, - ep_3550->max_dvc_qng); - ASC_PRT_NEXT(); - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - len = asc_prt_line(cp, leftlen, -" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ep_38C0800->adapter_scsi_id, ep_38C0800->max_host_qng, - ep_38C0800->max_dvc_qng); - ASC_PRT_NEXT(); - } else - { - len = asc_prt_line(cp, leftlen, -" Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ep_38C1600->adapter_scsi_id, ep_38C1600->max_host_qng, - ep_38C1600->max_dvc_qng); - ASC_PRT_NEXT(); - } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->termination; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->termination_lvd; - } else - { - word = ep_38C1600->termination_lvd; - } - switch (word) { - case 1: - termstr = "Low Off/High Off"; - break; - case 2: - termstr = "Low Off/High On"; - break; - case 3: - termstr = "Low On/High On"; - break; - default: - case 0: - termstr = "Automatic"; - break; - } + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + wordp = &ep_3550->serial_number_word1; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + wordp = &ep_38C0800->serial_number_word1; + } else { + wordp = &ep_38C1600->serial_number_word1; + } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - len = asc_prt_line(cp, leftlen, -" termination: %u (%s), bios_ctrl: 0x%x\n", - ep_3550->termination, termstr, ep_3550->bios_ctrl); - ASC_PRT_NEXT(); - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - len = asc_prt_line(cp, leftlen, -" termination: %u (%s), bios_ctrl: 0x%x\n", - ep_38C0800->termination_lvd, termstr, ep_38C0800->bios_ctrl); - ASC_PRT_NEXT(); - } else - { - len = asc_prt_line(cp, leftlen, -" termination: %u (%s), bios_ctrl: 0x%x\n", - ep_38C1600->termination_lvd, termstr, ep_38C1600->bios_ctrl); - ASC_PRT_NEXT(); - } + if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) { + len = + asc_prt_line(cp, leftlen, " Serial Number: %s\n", + serialstr); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " Serial Number Signature Not Present.\n"); + ASC_PRT_NEXT(); + } - len = asc_prt_line(cp, leftlen, -" Target ID: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %X", i); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->disc_enable; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->disc_enable; - } else - { - word = ep_38C1600->disc_enable; - } - len = asc_prt_line(cp, leftlen, -" Disconnects: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->tagqng_able; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->tagqng_able; - } else - { - word = ep_38C1600->tagqng_able; - } - len = asc_prt_line(cp, leftlen, -" Command Queuing: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->start_motor; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->start_motor; - } else - { - word = ep_38C1600->start_motor; - } - len = asc_prt_line(cp, leftlen, -" Start Motor: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - len = asc_prt_line(cp, leftlen, -" Synchronous Transfer:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep_3550->sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - } + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ep_3550->adapter_scsi_id, + ep_3550->max_host_qng, ep_3550->max_dvc_qng); + ASC_PRT_NEXT(); + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ep_38C0800->adapter_scsi_id, + ep_38C0800->max_host_qng, + ep_38C0800->max_dvc_qng); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ep_38C1600->adapter_scsi_id, + ep_38C1600->max_host_qng, + ep_38C1600->max_dvc_qng); + ASC_PRT_NEXT(); + } + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->termination; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->termination_lvd; + } else { + word = ep_38C1600->termination_lvd; + } + switch (word) { + case 1: + termstr = "Low Off/High Off"; + break; + case 2: + termstr = "Low Off/High On"; + break; + case 3: + termstr = "Low On/High On"; + break; + default: + case 0: + termstr = "Automatic"; + break; + } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - len = asc_prt_line(cp, leftlen, -" Ultra Transfer: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep_3550->ultra_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - } + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, + " termination: %u (%s), bios_ctrl: 0x%x\n", + ep_3550->termination, termstr, + ep_3550->bios_ctrl); + ASC_PRT_NEXT(); + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + len = asc_prt_line(cp, leftlen, + " termination: %u (%s), bios_ctrl: 0x%x\n", + ep_38C0800->termination_lvd, termstr, + ep_38C0800->bios_ctrl); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " termination: %u (%s), bios_ctrl: 0x%x\n", + ep_38C1600->termination_lvd, termstr, + ep_38C1600->bios_ctrl); + ASC_PRT_NEXT(); + } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) - { - word = ep_3550->wdtr_able; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) - { - word = ep_38C0800->wdtr_able; - } else - { - word = ep_38C1600->wdtr_able; - } - len = asc_prt_line(cp, leftlen, -" Wide Transfer: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 || - adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) - { - len = asc_prt_line(cp, leftlen, -" Synchronous Transfer Speed (Mhz):\n "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - char *speed_str; - - if (i == 0) - { - sdtr_speed = adv_dvc_varp->sdtr_speed1; - } else if (i == 4) - { - sdtr_speed = adv_dvc_varp->sdtr_speed2; - } else if (i == 8) - { - sdtr_speed = adv_dvc_varp->sdtr_speed3; - } else if (i == 12) - { - sdtr_speed = adv_dvc_varp->sdtr_speed4; - } - switch (sdtr_speed & ADV_MAX_TID) - { - case 0: speed_str = "Off"; break; - case 1: speed_str = " 5"; break; - case 2: speed_str = " 10"; break; - case 3: speed_str = " 20"; break; - case 4: speed_str = " 40"; break; - case 5: speed_str = " 80"; break; - default: speed_str = "Unk"; break; - } - len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str); - ASC_PRT_NEXT(); - if (i == 7) - { - len = asc_prt_line(cp, leftlen, "\n "); - ASC_PRT_NEXT(); - } - sdtr_speed >>= 4; - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - } + len = asc_prt_line(cp, leftlen, " Target ID: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %X", i); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->disc_enable; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->disc_enable; + } else { + word = ep_38C1600->disc_enable; + } + len = asc_prt_line(cp, leftlen, " Disconnects: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->tagqng_able; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->tagqng_able; + } else { + word = ep_38C1600->tagqng_able; + } + len = asc_prt_line(cp, leftlen, " Command Queuing: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->start_motor; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->start_motor; + } else { + word = ep_38C1600->start_motor; + } + len = asc_prt_line(cp, leftlen, " Start Motor: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep_3550-> + sdtr_able & ADV_TID_TO_TIDMASK(i)) ? + 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + } + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, " Ultra Transfer: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep_3550-> + ultra_able & ADV_TID_TO_TIDMASK(i)) + ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + } + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->wdtr_able; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->wdtr_able; + } else { + word = ep_38C1600->wdtr_able; + } + len = asc_prt_line(cp, leftlen, " Wide Transfer: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 || + adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) { + len = asc_prt_line(cp, leftlen, + " Synchronous Transfer Speed (Mhz):\n "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + char *speed_str; + + if (i == 0) { + sdtr_speed = adv_dvc_varp->sdtr_speed1; + } else if (i == 4) { + sdtr_speed = adv_dvc_varp->sdtr_speed2; + } else if (i == 8) { + sdtr_speed = adv_dvc_varp->sdtr_speed3; + } else if (i == 12) { + sdtr_speed = adv_dvc_varp->sdtr_speed4; + } + switch (sdtr_speed & ADV_MAX_TID) { + case 0: + speed_str = "Off"; + break; + case 1: + speed_str = " 5"; + break; + case 2: + speed_str = " 10"; + break; + case 3: + speed_str = " 20"; + break; + case 4: + speed_str = " 40"; + break; + case 5: + speed_str = " 80"; + break; + default: + speed_str = "Unk"; + break; + } + len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str); + ASC_PRT_NEXT(); + if (i == 7) { + len = asc_prt_line(cp, leftlen, "\n "); + ASC_PRT_NEXT(); + } + sdtr_speed >>= 4; + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + } - return totlen; + return totlen; } /* @@ -8062,60 +6871,60 @@ asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int leftlen; - int totlen; - int len; - int chip_scsi_id; - - boardp = ASC_BOARDP(shp); - - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n", - shp->host_no); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n", - shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun, - shp->max_channel); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", - shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize, - shp->cmd_per_lun); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" unchecked_isa_dma %d, use_clustering %d\n", - shp->unchecked_isa_dma, shp->use_clustering); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n", - boardp->flags, boardp->last_reset, jiffies, boardp->asc_n_io_port); - ASC_PRT_NEXT(); - - /* 'shp->n_io_port' may be truncated because it is only one byte. */ - len = asc_prt_line(cp, leftlen, -" io_port 0x%x, n_io_port 0x%x\n", - shp->io_port, shp->n_io_port); - ASC_PRT_NEXT(); - - if (ASC_NARROW_BOARD(boardp)) { - chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; - } else { - chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; - } + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + int chip_scsi_id; + + boardp = ASC_BOARDP(shost); + + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n", + shost->host_busy, shost->last_reset, shost->max_id, + shost->max_lun, shost->max_channel); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", + shost->unique_id, shost->can_queue, shost->this_id, + shost->sg_tablesize, shost->cmd_per_lun); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " unchecked_isa_dma %d, use_clustering %d\n", + shost->unchecked_isa_dma, shost->use_clustering); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n", + boardp->flags, boardp->last_reset, jiffies, + boardp->asc_n_io_port); + ASC_PRT_NEXT(); + + /* 'shost->n_io_port' may be truncated because it is only one byte. */ + len = asc_prt_line(cp, leftlen, + " io_port 0x%x, n_io_port 0x%x\n", + shost->io_port, shost->n_io_port); + ASC_PRT_NEXT(); + + if (ASC_NARROW_BOARD(boardp)) { + chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; + } else { + chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; + } - return totlen; + return totlen; } /* @@ -8129,178 +6938,181 @@ asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int chip_scsi_id; - int leftlen; - int totlen; - int len; - ASC_DVC_VAR *v; - ASC_DVC_CFG *c; - int i; - int renegotiate = 0; - - boardp = ASC_BOARDP(shp); - v = &boardp->dvc_var.asc_dvc_var; - c = &boardp->dvc_cfg.asc_dvc_cfg; - chip_scsi_id = c->chip_scsi_id; - - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", - shp->host_no); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n", - c->chip_version, c->lib_version, c->lib_serial_no, c->mcode_date); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" mcode_version 0x%x, err_code %u\n", - c->mcode_version, v->err_code); - ASC_PRT_NEXT(); - - /* Current number of commands waiting for the host. */ - len = asc_prt_line(cp, leftlen, -" Total Command Pending: %d\n", v->cur_total_qng); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Command Queuing:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - /* Current number of commands waiting for a device. */ - len = asc_prt_line(cp, leftlen, -" Command Queue Pending:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - /* Current limit on number of commands that can be sent to a device. */ - len = asc_prt_line(cp, leftlen, -" Command Queue Limit:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - /* Indicate whether the device has returned queue full status. */ - len = asc_prt_line(cp, leftlen, -" Command Queue Full:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) { - len = asc_prt_line(cp, leftlen, " %X:Y-%d", - i, boardp->queue_full_cnt[i]); - } else { - len = asc_prt_line(cp, leftlen, " %X:N", i); - } - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Synchronous Transfer:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - for (i = 0; i <= ASC_MAX_TID; i++) { - uchar syn_period_ix; - - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || - ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:", i); - ASC_PRT_NEXT(); - - if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) - { - len = asc_prt_line(cp, leftlen, " Asynchronous"); - ASC_PRT_NEXT(); - } else - { - syn_period_ix = - (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - 1); - - len = asc_prt_line(cp, leftlen, - " Transfer Period Factor: %d (%d.%d Mhz),", - v->sdtr_period_tbl[syn_period_ix], - 250 / v->sdtr_period_tbl[syn_period_ix], - ASC_TENTHS(250, v->sdtr_period_tbl[syn_period_ix])); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", - boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET); - ASC_PRT_NEXT(); - } - - if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { - len = asc_prt_line(cp, leftlen, "*\n"); - renegotiate = 1; - } else - { - len = asc_prt_line(cp, leftlen, "\n"); - } - ASC_PRT_NEXT(); - } + asc_board_t *boardp; + int chip_scsi_id; + int leftlen; + int totlen; + int len; + ASC_DVC_VAR *v; + ASC_DVC_CFG *c; + int i; + int renegotiate = 0; + + boardp = ASC_BOARDP(shost); + v = &boardp->dvc_var.asc_dvc_var; + c = &boardp->dvc_cfg.asc_dvc_cfg; + chip_scsi_id = c->chip_scsi_id; + + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n", + c->chip_version, c->lib_version, c->lib_serial_no, + c->mcode_date); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " mcode_version 0x%x, err_code %u\n", + c->mcode_version, v->err_code); + ASC_PRT_NEXT(); + + /* Current number of commands waiting for the host. */ + len = asc_prt_line(cp, leftlen, + " Total Command Pending: %d\n", v->cur_total_qng); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Command Queuing:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (v-> + use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? + 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + /* Current number of commands waiting for a device. */ + len = asc_prt_line(cp, leftlen, " Command Queue Pending:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + /* Current limit on number of commands that can be sent to a device. */ + len = asc_prt_line(cp, leftlen, " Command Queue Limit:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + /* Indicate whether the device has returned queue full status. */ + len = asc_prt_line(cp, leftlen, " Command Queue Full:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) { + len = asc_prt_line(cp, leftlen, " %X:Y-%d", + i, boardp->queue_full_cnt[i]); + } else { + len = asc_prt_line(cp, leftlen, " %X:N", i); + } + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (v-> + sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + for (i = 0; i <= ASC_MAX_TID; i++) { + uchar syn_period_ix; + + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || + ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:", i); + ASC_PRT_NEXT(); + + if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) { + len = asc_prt_line(cp, leftlen, " Asynchronous"); + ASC_PRT_NEXT(); + } else { + syn_period_ix = + (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - + 1); + + len = asc_prt_line(cp, leftlen, + " Transfer Period Factor: %d (%d.%d Mhz),", + v->sdtr_period_tbl[syn_period_ix], + 250 / + v->sdtr_period_tbl[syn_period_ix], + ASC_TENTHS(250, + v-> + sdtr_period_tbl + [syn_period_ix])); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", + boardp-> + sdtr_data[i] & ASC_SYN_MAX_OFFSET); + ASC_PRT_NEXT(); + } + + if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { + len = asc_prt_line(cp, leftlen, "*\n"); + renegotiate = 1; + } else { + len = asc_prt_line(cp, leftlen, "\n"); + } + ASC_PRT_NEXT(); + } - if (renegotiate) - { - len = asc_prt_line(cp, leftlen, - " * = Re-negotiation pending before next command.\n"); - ASC_PRT_NEXT(); - } + if (renegotiate) { + len = asc_prt_line(cp, leftlen, + " * = Re-negotiation pending before next command.\n"); + ASC_PRT_NEXT(); + } - return totlen; + return totlen; } /* @@ -8314,237 +7126,242 @@ asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; - int leftlen; - int totlen; - int len; - int i; - ADV_DVC_VAR *v; - ADV_DVC_CFG *c; - AdvPortAddr iop_base; - ushort chip_scsi_id; - ushort lramword; - uchar lrambyte; - ushort tagqng_able; - ushort sdtr_able, wdtr_able; - ushort wdtr_done, sdtr_done; - ushort period = 0; - int renegotiate = 0; - - boardp = ASC_BOARDP(shp); - v = &boardp->dvc_var.adv_dvc_var; - c = &boardp->dvc_cfg.adv_dvc_cfg; - iop_base = v->iop_base; - chip_scsi_id = v->chip_scsi_id; - - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, -"\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", - shp->host_no); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" iop_base 0x%lx, cable_detect: %X, err_code %u\n", - v->iop_base, - AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1) & CABLE_DETECT, - v->err_code); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n", - c->chip_version, c->lib_version, c->mcode_date, c->mcode_version); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - len = asc_prt_line(cp, leftlen, -" Queuing Enabled:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Queue Limit:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, lrambyte); - - len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" Command Pending:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, lrambyte); - - len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - len = asc_prt_line(cp, leftlen, -" Wide Enabled:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done); - len = asc_prt_line(cp, leftlen, -" Transfer Bit Width:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), - lramword); - - len = asc_prt_line(cp, leftlen, " %X:%d", - i, (lramword & 0x8000) ? 16 : 8); - ASC_PRT_NEXT(); - - if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) && - (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { - len = asc_prt_line(cp, leftlen, "*"); - ASC_PRT_NEXT(); - renegotiate = 1; - } - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - len = asc_prt_line(cp, leftlen, -" Synchronous Enabled:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:%c", - i, (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done); - for (i = 0; i <= ADV_MAX_TID; i++) { - - AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), - lramword); - lramword &= ~0x8000; - - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || - ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - - len = asc_prt_line(cp, leftlen, " %X:", i); - ASC_PRT_NEXT(); - - if ((lramword & 0x1F) == 0) /* Check for REQ/ACK Offset 0. */ - { - len = asc_prt_line(cp, leftlen, " Asynchronous"); - ASC_PRT_NEXT(); - } else - { - len = asc_prt_line(cp, leftlen, " Transfer Period Factor: "); - ASC_PRT_NEXT(); - - if ((lramword & 0x1F00) == 0x1100) /* 80 Mhz */ - { - len = asc_prt_line(cp, leftlen, "9 (80.0 Mhz),"); - ASC_PRT_NEXT(); - } else if ((lramword & 0x1F00) == 0x1000) /* 40 Mhz */ - { - len = asc_prt_line(cp, leftlen, "10 (40.0 Mhz),"); - ASC_PRT_NEXT(); - } else /* 20 Mhz or below. */ - { - period = (((lramword >> 8) * 25) + 50)/4; - - if (period == 0) /* Should never happen. */ - { - len = asc_prt_line(cp, leftlen, "%d (? Mhz), "); - ASC_PRT_NEXT(); - } else - { - len = asc_prt_line(cp, leftlen, - "%d (%d.%d Mhz),", - period, 250/period, ASC_TENTHS(250, period)); - ASC_PRT_NEXT(); - } - } - - len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", - lramword & 0x1F); - ASC_PRT_NEXT(); - } - - if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { - len = asc_prt_line(cp, leftlen, "*\n"); - renegotiate = 1; - } else - { - len = asc_prt_line(cp, leftlen, "\n"); - } - ASC_PRT_NEXT(); - } + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + int i; + ADV_DVC_VAR *v; + ADV_DVC_CFG *c; + AdvPortAddr iop_base; + ushort chip_scsi_id; + ushort lramword; + uchar lrambyte; + ushort tagqng_able; + ushort sdtr_able, wdtr_able; + ushort wdtr_done, sdtr_done; + ushort period = 0; + int renegotiate = 0; + + boardp = ASC_BOARDP(shost); + v = &boardp->dvc_var.adv_dvc_var; + c = &boardp->dvc_cfg.adv_dvc_cfg; + iop_base = v->iop_base; + chip_scsi_id = v->chip_scsi_id; + + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " iop_base 0x%lx, cable_detect: %X, err_code %u\n", + v->iop_base, + AdvReadWordRegister(iop_base, + IOPW_SCSI_CFG1) & CABLE_DETECT, + v->err_code); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n", + c->chip_version, c->lib_version, c->mcode_date, + c->mcode_version); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + len = asc_prt_line(cp, leftlen, " Queuing Enabled:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Queue Limit:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, + lrambyte); + + len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Command Pending:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, + lrambyte); + + len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + len = asc_prt_line(cp, leftlen, " Wide Enabled:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done); + len = asc_prt_line(cp, leftlen, " Transfer Bit Width:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + AdvReadWordLram(iop_base, + ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), + lramword); + + len = asc_prt_line(cp, leftlen, " %X:%d", + i, (lramword & 0x8000) ? 16 : 8); + ASC_PRT_NEXT(); + + if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) && + (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { + len = asc_prt_line(cp, leftlen, "*"); + ASC_PRT_NEXT(); + renegotiate = 1; + } + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + len = asc_prt_line(cp, leftlen, " Synchronous Enabled:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done); + for (i = 0; i <= ADV_MAX_TID; i++) { + + AdvReadWordLram(iop_base, + ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), + lramword); + lramword &= ~0x8000; + + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || + ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:", i); + ASC_PRT_NEXT(); + + if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */ + len = asc_prt_line(cp, leftlen, " Asynchronous"); + ASC_PRT_NEXT(); + } else { + len = + asc_prt_line(cp, leftlen, + " Transfer Period Factor: "); + ASC_PRT_NEXT(); + + if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */ + len = + asc_prt_line(cp, leftlen, "9 (80.0 Mhz),"); + ASC_PRT_NEXT(); + } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */ + len = + asc_prt_line(cp, leftlen, "10 (40.0 Mhz),"); + ASC_PRT_NEXT(); + } else { /* 20 Mhz or below. */ + + period = (((lramword >> 8) * 25) + 50) / 4; + + if (period == 0) { /* Should never happen. */ + len = + asc_prt_line(cp, leftlen, + "%d (? Mhz), "); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + "%d (%d.%d Mhz),", + period, 250 / period, + ASC_TENTHS(250, + period)); + ASC_PRT_NEXT(); + } + } + + len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", + lramword & 0x1F); + ASC_PRT_NEXT(); + } + + if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { + len = asc_prt_line(cp, leftlen, "*\n"); + renegotiate = 1; + } else { + len = asc_prt_line(cp, leftlen, "\n"); + } + ASC_PRT_NEXT(); + } - if (renegotiate) - { - len = asc_prt_line(cp, leftlen, - " * = Re-negotiation pending before next command.\n"); - ASC_PRT_NEXT(); - } + if (renegotiate) { + len = asc_prt_line(cp, leftlen, + " * = Re-negotiation pending before next command.\n"); + ASC_PRT_NEXT(); + } - return totlen; + return totlen; } /* @@ -8553,30 +7370,30 @@ asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen) * Copy proc information to a read buffer taking into account the current * read offset in the file and the remaining space in the read buffer. */ -STATIC int +static int asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, - char *cp, int cplen) + char *cp, int cplen) { - int cnt = 0; - - ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n", - (unsigned) offset, (unsigned) advoffset, cplen); - if (offset <= advoffset) { - /* Read offset below current offset, copy everything. */ - cnt = min(cplen, leftlen); - ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", - (ulong) curbuf, (ulong) cp, cnt); - memcpy(curbuf, cp, cnt); - } else if (offset < advoffset + cplen) { - /* Read offset within current range, partial copy. */ - cnt = (advoffset + cplen) - offset; - cp = (cp + cplen) - cnt; - cnt = min(cnt, leftlen); - ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", - (ulong) curbuf, (ulong) cp, cnt); - memcpy(curbuf, cp, cnt); - } - return cnt; + int cnt = 0; + + ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n", + (unsigned)offset, (unsigned)advoffset, cplen); + if (offset <= advoffset) { + /* Read offset below current offset, copy everything. */ + cnt = min(cplen, leftlen); + ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", + (ulong)curbuf, (ulong)cp, cnt); + memcpy(curbuf, cp, cnt); + } else if (offset < advoffset + cplen) { + /* Read offset within current range, partial copy. */ + cnt = (advoffset + cplen) - offset; + cp = (cp + cplen) - cnt; + cnt = min(cnt, leftlen); + ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", + (ulong)curbuf, (ulong)cp, cnt); + memcpy(curbuf, cp, cnt); + } + return cnt; } /* @@ -8590,29 +7407,27 @@ asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes. */ -STATIC int -asc_prt_line(char *buf, int buflen, char *fmt, ...) +static int asc_prt_line(char *buf, int buflen, char *fmt, ...) { - va_list args; - int ret; - char s[ASC_PRTLINE_SIZE]; - - va_start(args, fmt); - ret = vsprintf(s, fmt, args); - ASC_ASSERT(ret < ASC_PRTLINE_SIZE); - if (buf == NULL) { - (void) printk(s); - ret = 0; - } else { - ret = min(buflen, ret); - memcpy(buf, s, ret); - } - va_end(args); - return ret; + va_list args; + int ret; + char s[ASC_PRTLINE_SIZE]; + + va_start(args, fmt); + ret = vsprintf(s, fmt, args); + ASC_ASSERT(ret < ASC_PRTLINE_SIZE); + if (buf == NULL) { + (void)printk(s); + ret = 0; + } else { + ret = min(buflen, ret); + memcpy(buf, s, ret); + } + va_end(args); + return ret; } #endif /* CONFIG_PROC_FS */ - /* * --- Functions Required by the Asc Library */ @@ -8623,31 +7438,28 @@ asc_prt_line(char *buf, int buflen, char *fmt, ...) * from a timer interrupt, because this function may be * called when interrupts are disabled. */ -STATIC void -DvcSleepMilliSecond(ADV_DCNT n) +static void DvcSleepMilliSecond(ADV_DCNT n) { - ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong) n); - mdelay(n); + ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n); + mdelay(n); } /* * Currently and inline noop but leave as a placeholder. * Leave DvcEnterCritical() as a noop placeholder. */ -STATIC inline ulong -DvcEnterCritical(void) +static inline ulong DvcEnterCritical(void) { - return 0; + return 0; } /* * Critical sections are all protected by the board spinlock. * Leave DvcLeaveCritical() as a noop placeholder. */ -STATIC inline void -DvcLeaveCritical(ulong flags) +static inline void DvcLeaveCritical(ulong flags) { - return; + return; } /* @@ -8660,20 +7472,20 @@ DvcLeaveCritical(ulong flags) * Description: * Output an ASC_SCSI_Q structure to the chip */ -STATIC void +static void DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) { - int i; - - ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words); - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - if (i == 4 || i == 20) { - continue; - } - outpw(iop_base + IOP_RAM_DATA, - ((ushort) outbuf[i + 1] << 8) | outbuf[i]); - } + int i; + + ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words); + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + if (i == 4 || i == 20) { + continue; + } + outpw(iop_base + IOP_RAM_DATA, + ((ushort)outbuf[i + 1] << 8) | outbuf[i]); + } } /* @@ -8686,52 +7498,46 @@ DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) * Description: * Input an ASC_QDONE_INFO structure from the chip */ -STATIC void +static void DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) { - int i; - ushort word; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - if (i == 10) { - continue; - } - word = inpw(iop_base + IOP_RAM_DATA); - inbuf[i] = word & 0xff; - inbuf[i + 1] = (word >> 8) & 0xff; - } - ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words); + int i; + ushort word; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + if (i == 10) { + continue; + } + word = inpw(iop_base + IOP_RAM_DATA); + inbuf[i] = word & 0xff; + inbuf[i + 1] = (word >> 8) & 0xff; + } + ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words); } /* * Read a PCI configuration byte. */ -STATIC uchar __init -DvcReadPCIConfigByte( - ASC_DVC_VAR *asc_dvc, - ushort offset) +static uchar __init DvcReadPCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset) { #ifdef CONFIG_PCI - uchar byte_data; - pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); - return byte_data; + uchar byte_data; + pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); + return byte_data; #else /* !defined(CONFIG_PCI) */ - return 0; + return 0; #endif /* !defined(CONFIG_PCI) */ } /* * Write a PCI configuration byte. */ -STATIC void __init -DvcWritePCIConfigByte( - ASC_DVC_VAR *asc_dvc, - ushort offset, - uchar byte_data) +static void __init +DvcWritePCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) { #ifdef CONFIG_PCI - pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); + pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); #endif /* CONFIG_PCI */ } @@ -8739,51 +7545,43 @@ DvcWritePCIConfigByte( * Return the BIOS address of the adapter at the specified * I/O port and with the specified bus type. */ -STATIC ushort __init -AscGetChipBiosAddress( - PortAddr iop_base, - ushort bus_type) +static ushort __init AscGetChipBiosAddress(PortAddr iop_base, ushort bus_type) { - ushort cfg_lsw; - ushort bios_addr; - - /* - * The PCI BIOS is re-located by the motherboard BIOS. Because - * of this the driver can not determine where a PCI BIOS is - * loaded and executes. - */ - if (bus_type & ASC_IS_PCI) - { - return(0); - } - + ushort cfg_lsw; + ushort bios_addr; + + /* + * The PCI BIOS is re-located by the motherboard BIOS. Because + * of this the driver can not determine where a PCI BIOS is + * loaded and executes. + */ + if (bus_type & ASC_IS_PCI) { + return (0); + } #ifdef CONFIG_ISA - if((bus_type & ASC_IS_EISA) != 0) - { - cfg_lsw = AscGetEisaChipCfg(iop_base); - cfg_lsw &= 0x000F; - bios_addr = (ushort)(ASC_BIOS_MIN_ADDR + - (cfg_lsw * ASC_BIOS_BANK_SIZE)); - return(bios_addr); - }/* if */ + if ((bus_type & ASC_IS_EISA) != 0) { + cfg_lsw = AscGetEisaChipCfg(iop_base); + cfg_lsw &= 0x000F; + bios_addr = (ushort)(ASC_BIOS_MIN_ADDR + + (cfg_lsw * ASC_BIOS_BANK_SIZE)); + return (bios_addr); + } /* if */ #endif /* CONFIG_ISA */ - cfg_lsw = AscGetChipCfgLsw(iop_base); + cfg_lsw = AscGetChipCfgLsw(iop_base); - /* - * ISA PnP uses the top bit as the 32K BIOS flag - */ - if (bus_type == ASC_IS_ISAPNP) - { - cfg_lsw &= 0x7FFF; - }/* if */ - - bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + - ASC_BIOS_MIN_ADDR); - return(bios_addr); + /* + * ISA PnP uses the top bit as the 32K BIOS flag + */ + if (bus_type == ASC_IS_ISAPNP) { + cfg_lsw &= 0x7FFF; + } + /* if */ + bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + + ASC_BIOS_MIN_ADDR); + return (bios_addr); } - /* * --- Functions Required by the Adv Library */ @@ -8801,49 +7599,44 @@ AscGetChipBiosAddress( */ ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq, - uchar *vaddr, ADV_SDCNT *lenp, int flag) + uchar *vaddr, ADV_SDCNT *lenp, int flag) { - ADV_PADDR paddr; + ADV_PADDR paddr; - paddr = virt_to_bus(vaddr); + paddr = virt_to_bus(vaddr); - ASC_DBG4(4, - "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n", - (ulong) vaddr, (ulong) lenp, (ulong) *((ulong *) lenp), (ulong) paddr); + ASC_DBG4(4, + "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n", + (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp), + (ulong)paddr); - return paddr; + return paddr; } /* * Read a PCI configuration byte. */ -STATIC uchar __init -DvcAdvReadPCIConfigByte( - ADV_DVC_VAR *asc_dvc, - ushort offset) +static uchar __init DvcAdvReadPCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset) { #ifdef CONFIG_PCI - uchar byte_data; - pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); - return byte_data; + uchar byte_data; + pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); + return byte_data; #else /* CONFIG_PCI */ - return 0; + return 0; #endif /* CONFIG_PCI */ } /* * Write a PCI configuration byte. */ -STATIC void __init -DvcAdvWritePCIConfigByte( - ADV_DVC_VAR *asc_dvc, - ushort offset, - uchar byte_data) +static void __init +DvcAdvWritePCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) { #ifdef CONFIG_PCI - pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); + pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); #else /* CONFIG_PCI */ - return; + return; #endif /* CONFIG_PCI */ } @@ -8862,97 +7655,98 @@ DvcAdvWritePCIConfigByte( * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen) +static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen) { - int leftlen; - int totlen; - int len; - struct asc_stats *s; - asc_board_t *boardp; - - leftlen = cplen; - totlen = len = 0; - - boardp = ASC_BOARDP(shp); - s = &boardp->asc_stats; - - len = asc_prt_line(cp, leftlen, -"\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", shp->host_no); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n", - s->queuecommand, s->reset, s->biosparam, s->interrupt); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n", - s->callback, s->done, s->build_error, s->adv_build_noreq, - s->adv_build_nosg); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n", - s->exe_noerror, s->exe_busy, s->exe_error, s->exe_unknown); - ASC_PRT_NEXT(); - - /* - * Display data transfer statistics. - */ - if (s->cont_cnt > 0) { - len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ", - s->cont_xfer/2, - ASC_TENTHS(s->cont_xfer, 2)); - ASC_PRT_NEXT(); - - /* Contiguous transfer average size */ - len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n", - (s->cont_xfer/2)/s->cont_cnt, - ASC_TENTHS((s->cont_xfer/2), s->cont_cnt)); - ASC_PRT_NEXT(); - } + int leftlen; + int totlen; + int len; + struct asc_stats *s; + asc_board_t *boardp; - if (s->sg_cnt > 0) { + leftlen = cplen; + totlen = len = 0; + + boardp = ASC_BOARDP(shost); + s = &boardp->asc_stats; + + len = asc_prt_line(cp, leftlen, + "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n", + s->queuecommand, s->reset, s->biosparam, + s->interrupt); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n", + s->callback, s->done, s->build_error, + s->adv_build_noreq, s->adv_build_nosg); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n", + s->exe_noerror, s->exe_busy, s->exe_error, + s->exe_unknown); + ASC_PRT_NEXT(); + + /* + * Display data transfer statistics. + */ + if (s->cont_cnt > 0) { + len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ", + s->cont_xfer / 2, + ASC_TENTHS(s->cont_xfer, 2)); + ASC_PRT_NEXT(); + + /* Contiguous transfer average size */ + len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n", + (s->cont_xfer / 2) / s->cont_cnt, + ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt)); + ASC_PRT_NEXT(); + } - len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ", - s->sg_cnt, s->sg_elem); - ASC_PRT_NEXT(); + if (s->sg_cnt > 0) { - len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n", - s->sg_xfer/2, - ASC_TENTHS(s->sg_xfer, 2)); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ", + s->sg_cnt, s->sg_elem); + ASC_PRT_NEXT(); - /* Scatter gather transfer statistics */ - len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ", - s->sg_elem/s->sg_cnt, - ASC_TENTHS(s->sg_elem, s->sg_cnt)); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n", + s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2)); + ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ", - (s->sg_xfer/2)/s->sg_elem, - ASC_TENTHS((s->sg_xfer/2), s->sg_elem)); - ASC_PRT_NEXT(); + /* Scatter gather transfer statistics */ + len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ", + s->sg_elem / s->sg_cnt, + ASC_TENTHS(s->sg_elem, s->sg_cnt)); + ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n", - (s->sg_xfer/2)/s->sg_cnt, - ASC_TENTHS((s->sg_xfer/2), s->sg_cnt)); - ASC_PRT_NEXT(); - } + len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ", + (s->sg_xfer / 2) / s->sg_elem, + ASC_TENTHS((s->sg_xfer / 2), s->sg_elem)); + ASC_PRT_NEXT(); - /* - * Display request queuing statistics. - */ - len = asc_prt_line(cp, leftlen, -" Active and Waiting Request Queues (Time Unit: %d HZ):\n", HZ); - ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n", + (s->sg_xfer / 2) / s->sg_cnt, + ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt)); + ASC_PRT_NEXT(); + } + /* + * Display request queuing statistics. + */ + len = asc_prt_line(cp, leftlen, + " Active and Waiting Request Queues (Time Unit: %d HZ):\n", + HZ); + ASC_PRT_NEXT(); - return totlen; + return totlen; } /* @@ -8967,70 +7761,89 @@ asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen) * Return the number of characters copied into 'cp'. No more than * 'cplen' characters will be copied to 'cp'. */ -STATIC int -asc_prt_target_stats(struct Scsi_Host *shp, int tgt_id, char *cp, int cplen) +static int +asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen) { - int leftlen; - int totlen; - int len; - struct asc_stats *s; - ushort chip_scsi_id; - asc_board_t *boardp; - asc_queue_t *active; - asc_queue_t *waiting; - - leftlen = cplen; - totlen = len = 0; - - boardp = ASC_BOARDP(shp); - s = &boardp->asc_stats; - - active = &ASC_BOARDP(shp)->active; - waiting = &ASC_BOARDP(shp)->waiting; - - if (ASC_NARROW_BOARD(boardp)) { - chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; - } else { - chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; - } + int leftlen; + int totlen; + int len; + struct asc_stats *s; + ushort chip_scsi_id; + asc_board_t *boardp; + asc_queue_t *active; + asc_queue_t *waiting; - if ((chip_scsi_id == tgt_id) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) { - return 0; - } + leftlen = cplen; + totlen = len = 0; + + boardp = ASC_BOARDP(shost); + s = &boardp->asc_stats; + + active = &ASC_BOARDP(shost)->active; + waiting = &ASC_BOARDP(shost)->waiting; + + if (ASC_NARROW_BOARD(boardp)) { + chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; + } else { + chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; + } + + if ((chip_scsi_id == tgt_id) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) { + return 0; + } - do { - if (active->q_tot_cnt[tgt_id] > 0 || waiting->q_tot_cnt[tgt_id] > 0) { - len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n", - active->q_cur_cnt[tgt_id], active->q_max_cnt[tgt_id], - active->q_tot_cnt[tgt_id], - active->q_min_tim[tgt_id], active->q_max_tim[tgt_id], - (active->q_tot_cnt[tgt_id] == 0) ? 0 : - (active->q_tot_tim[tgt_id]/active->q_tot_cnt[tgt_id]), - (active->q_tot_cnt[tgt_id] == 0) ? 0 : - ASC_TENTHS(active->q_tot_tim[tgt_id], - active->q_tot_cnt[tgt_id])); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, -" waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n", - waiting->q_cur_cnt[tgt_id], waiting->q_max_cnt[tgt_id], - waiting->q_tot_cnt[tgt_id], - waiting->q_min_tim[tgt_id], waiting->q_max_tim[tgt_id], - (waiting->q_tot_cnt[tgt_id] == 0) ? 0 : - (waiting->q_tot_tim[tgt_id]/waiting->q_tot_cnt[tgt_id]), - (waiting->q_tot_cnt[tgt_id] == 0) ? 0 : - ASC_TENTHS(waiting->q_tot_tim[tgt_id], - waiting->q_tot_cnt[tgt_id])); - ASC_PRT_NEXT(); - } - } while (0); - - return totlen; + do { + if (active->q_tot_cnt[tgt_id] > 0 + || waiting->q_tot_cnt[tgt_id] > 0) { + len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n", + active->q_cur_cnt[tgt_id], + active->q_max_cnt[tgt_id], + active->q_tot_cnt[tgt_id], + active->q_min_tim[tgt_id], + active->q_max_tim[tgt_id], + (active->q_tot_cnt[tgt_id] == + 0) ? 0 : (active-> + q_tot_tim[tgt_id] / + active-> + q_tot_cnt[tgt_id]), + (active->q_tot_cnt[tgt_id] == + 0) ? 0 : ASC_TENTHS(active-> + q_tot_tim + [tgt_id], + active-> + q_tot_cnt + [tgt_id])); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n", + waiting->q_cur_cnt[tgt_id], + waiting->q_max_cnt[tgt_id], + waiting->q_tot_cnt[tgt_id], + waiting->q_min_tim[tgt_id], + waiting->q_max_tim[tgt_id], + (waiting->q_tot_cnt[tgt_id] == + 0) ? 0 : (waiting-> + q_tot_tim[tgt_id] / + waiting-> + q_tot_cnt[tgt_id]), + (waiting->q_tot_cnt[tgt_id] == + 0) ? 0 : ASC_TENTHS(waiting-> + q_tot_tim + [tgt_id], + waiting-> + q_tot_cnt + [tgt_id])); + ASC_PRT_NEXT(); + } + } while (0); + + return totlen; } #endif /* CONFIG_PROC_FS */ #endif /* ADVANSYS_STATS */ @@ -9039,207 +7852,181 @@ asc_prt_target_stats(struct Scsi_Host *shp, int tgt_id, char *cp, int cplen) /* * asc_prt_scsi_host() */ -STATIC void -asc_prt_scsi_host(struct Scsi_Host *s) +static void asc_prt_scsi_host(struct Scsi_Host *s) { - asc_board_t *boardp; - - boardp = ASC_BOARDP(s); - - printk("Scsi_Host at addr 0x%lx\n", (ulong) s); - printk( -" host_busy %u, host_no %d, last_reset %d,\n", - s->host_busy, s->host_no, - (unsigned) s->last_reset); - - printk( -" base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n", - (ulong) s->base, (ulong) s->io_port, s->n_io_port, s->irq); - - printk( -" dma_channel %d, this_id %d, can_queue %d,\n", - s->dma_channel, s->this_id, s->can_queue); - - printk( -" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", - s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); - - if (ASC_NARROW_BOARD(boardp)) { - asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var); - asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg); - } else { - asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var); - asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg); - } + asc_board_t *boardp; + + boardp = ASC_BOARDP(s); + + printk("Scsi_Host at addr 0x%lx\n", (ulong)s); + printk(" host_busy %u, host_no %d, last_reset %d,\n", + s->host_busy, s->host_no, (unsigned)s->last_reset); + + printk(" base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n", + (ulong)s->base, (ulong)s->io_port, s->n_io_port, s->irq); + + printk(" dma_channel %d, this_id %d, can_queue %d,\n", + s->dma_channel, s->this_id, s->can_queue); + + printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", + s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); + + if (ASC_NARROW_BOARD(boardp)) { + asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var); + asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg); + } else { + asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var); + asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg); + } } /* * asc_prt_scsi_cmnd() */ -STATIC void -asc_prt_scsi_cmnd(struct scsi_cmnd *s) +static void asc_prt_scsi_cmnd(struct scsi_cmnd *s) { - printk("struct scsi_cmnd at addr 0x%lx\n", (ulong) s); + printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s); - printk( -" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n", - (ulong) s->device->host, (ulong) s->device, s->device->id, s->device->lun, - s->device->channel); + printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n", + (ulong)s->device->host, (ulong)s->device, s->device->id, + s->device->lun, s->device->channel); - asc_prt_hex(" CDB", s->cmnd, s->cmd_len); + asc_prt_hex(" CDB", s->cmnd, s->cmd_len); - printk ( -"sc_data_direction %u, resid %d\n", - s->sc_data_direction, s->resid); + printk("sc_data_direction %u, resid %d\n", + s->sc_data_direction, s->resid); - printk( -" use_sg %u, sglist_len %u\n", - s->use_sg, s->sglist_len); + printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len); - printk( -" serial_number 0x%x, retries %d, allowed %d\n", - (unsigned) s->serial_number, s->retries, s->allowed); + printk(" serial_number 0x%x, retries %d, allowed %d\n", + (unsigned)s->serial_number, s->retries, s->allowed); - printk( -" timeout_per_command %d\n", - s->timeout_per_command); + printk(" timeout_per_command %d\n", s->timeout_per_command); - printk( -" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n", - (ulong) s->scsi_done, (ulong) s->done, - (ulong) s->host_scribble, s->result); + printk + (" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n", + (ulong)s->scsi_done, (ulong)s->done, (ulong)s->host_scribble, + s->result); - printk( -" tag %u, pid %u\n", - (unsigned) s->tag, (unsigned) s->pid); + printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid); } /* * asc_prt_asc_dvc_var() */ -STATIC void -asc_prt_asc_dvc_var(ASC_DVC_VAR *h) +static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h) { - printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong) h); - - printk( -" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl %d,\n", - h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); - - printk( -" bus_type %d, isr_callback 0x%lx, exe_callback 0x%lx, init_sdtr 0x%x,\n", - h->bus_type, (ulong) h->isr_callback, (ulong) h->exe_callback, - (unsigned) h->init_sdtr); - - printk( -" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, chip_no 0x%x,\n", - (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng, - (unsigned) h->unit_not_ready, (unsigned) h->chip_no); - - printk( -" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait %u,\n", - (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor, - (unsigned) h->scsi_reset_wait); - - printk( -" is_in_int %u, max_total_qng %u, cur_total_qng %u, in_critical_cnt %u,\n", - (unsigned) h->is_in_int, (unsigned) h->max_total_qng, - (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt); - - printk( -" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, pci_fix_asyn_xfer 0x%x,\n", - (unsigned) h->last_q_shortage, (unsigned) h->init_state, - (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer); - - printk( -" cfg 0x%lx, irq_no 0x%x\n", - (ulong) h->cfg, (unsigned) h->irq_no); + printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h); + + printk + (" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl %d,\n", + h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); + + printk + (" bus_type %d, isr_callback 0x%lx, exe_callback 0x%lx, init_sdtr 0x%x,\n", + h->bus_type, (ulong)h->isr_callback, (ulong)h->exe_callback, + (unsigned)h->init_sdtr); + + printk + (" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, chip_no 0x%x,\n", + (unsigned)h->sdtr_done, (unsigned)h->use_tagged_qng, + (unsigned)h->unit_not_ready, (unsigned)h->chip_no); + + printk + (" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait %u,\n", + (unsigned)h->queue_full_or_busy, (unsigned)h->start_motor, + (unsigned)h->scsi_reset_wait); + + printk + (" is_in_int %u, max_total_qng %u, cur_total_qng %u, in_critical_cnt %u,\n", + (unsigned)h->is_in_int, (unsigned)h->max_total_qng, + (unsigned)h->cur_total_qng, (unsigned)h->in_critical_cnt); + + printk + (" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, pci_fix_asyn_xfer 0x%x,\n", + (unsigned)h->last_q_shortage, (unsigned)h->init_state, + (unsigned)h->no_scam, (unsigned)h->pci_fix_asyn_xfer); + + printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no); } /* * asc_prt_asc_dvc_cfg() */ -STATIC void -asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) +static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) { - printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong) h); - - printk( -" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n", - h->can_tagged_qng, h->cmd_qng_enabled); - printk( -" disc_enable 0x%x, sdtr_enable 0x%x,\n", - h->disc_enable, h->sdtr_enable); - - printk( -" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", - h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, - h->chip_version); - - printk( -" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n", - to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version, - h->mcode_date); - - printk( -" mcode_version %d, overrun_buf 0x%lx\n", - h->mcode_version, (ulong) h->overrun_buf); + printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h); + + printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n", + h->can_tagged_qng, h->cmd_qng_enabled); + printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n", + h->disc_enable, h->sdtr_enable); + + printk + (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", + h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, + h->chip_version); + + printk + (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n", + to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version, + h->mcode_date); + + printk(" mcode_version %d, overrun_buf 0x%lx\n", + h->mcode_version, (ulong)h->overrun_buf); } /* * asc_prt_asc_scsi_q() */ -STATIC void -asc_prt_asc_scsi_q(ASC_SCSI_Q *q) +static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q) { - ASC_SG_HEAD *sgp; - int i; - - printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong) q); - - printk( -" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n", - q->q2.target_ix, q->q1.target_lun, - (ulong) q->q2.srb_ptr, q->q2.tag_code); - - printk( -" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", - (ulong) le32_to_cpu(q->q1.data_addr), - (ulong) le32_to_cpu(q->q1.data_cnt), - (ulong) le32_to_cpu(q->q1.sense_addr), q->q1.sense_len); - - printk( -" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n", - (ulong) q->cdbptr, q->q2.cdb_len, - (ulong) q->sg_head, q->q1.sg_queue_cnt); - - if (q->sg_head) { - sgp = q->sg_head; - printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong) sgp); - printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt); - for (i = 0; i < sgp->entry_cnt; i++) { - printk(" [%u]: addr 0x%lx, bytes %lu\n", - i, (ulong) le32_to_cpu(sgp->sg_list[i].addr), - (ulong) le32_to_cpu(sgp->sg_list[i].bytes)); - } + ASC_SG_HEAD *sgp; + int i; + + printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q); + + printk + (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n", + q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr, + q->q2.tag_code); + + printk + (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", + (ulong)le32_to_cpu(q->q1.data_addr), + (ulong)le32_to_cpu(q->q1.data_cnt), + (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len); + + printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n", + (ulong)q->cdbptr, q->q2.cdb_len, + (ulong)q->sg_head, q->q1.sg_queue_cnt); + + if (q->sg_head) { + sgp = q->sg_head; + printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp); + printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, + sgp->queue_cnt); + for (i = 0; i < sgp->entry_cnt; i++) { + printk(" [%u]: addr 0x%lx, bytes %lu\n", + i, (ulong)le32_to_cpu(sgp->sg_list[i].addr), + (ulong)le32_to_cpu(sgp->sg_list[i].bytes)); + } - } + } } /* * asc_prt_asc_qdone_info() */ -STATIC void -asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) +static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) { - printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong) q); - printk( -" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n", - (ulong) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, - q->d2.tag_code); - printk( -" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n", - q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); + printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q); + printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n", + (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, + q->d2.tag_code); + printk + (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n", + q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); } /* @@ -9247,41 +8034,33 @@ asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) * * Display an ADV_DVC_VAR structure. */ -STATIC void -asc_prt_adv_dvc_var(ADV_DVC_VAR *h) +static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h) { - printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong) h); - - printk( -" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", - (ulong) h->iop_base, h->err_code, (unsigned) h->ultra_able); - - printk( -" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n", - (ulong) h->isr_callback, (unsigned) h->sdtr_able, - (unsigned) h->wdtr_able); - - printk( -" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n", - (unsigned) h->start_motor, - (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no); - - printk( -" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n", - (unsigned) h->max_host_qng, (unsigned) h->max_dvc_qng, - (ulong) h->carr_freelist); - - printk( -" icq_sp 0x%lx, irq_sp 0x%lx\n", - (ulong) h->icq_sp, (ulong) h->irq_sp); - - printk( -" no_scam 0x%x, tagqng_able 0x%x\n", - (unsigned) h->no_scam, (unsigned) h->tagqng_able); - - printk( -" chip_scsi_id 0x%x, cfg 0x%lx\n", - (unsigned) h->chip_scsi_id, (ulong) h->cfg); + printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h); + + printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", + (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able); + + printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n", + (ulong)h->isr_callback, (unsigned)h->sdtr_able, + (unsigned)h->wdtr_able); + + printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n", + (unsigned)h->start_motor, + (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no); + + printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n", + (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng, + (ulong)h->carr_freelist); + + printk(" icq_sp 0x%lx, irq_sp 0x%lx\n", + (ulong)h->icq_sp, (ulong)h->irq_sp); + + printk(" no_scam 0x%x, tagqng_able 0x%x\n", + (unsigned)h->no_scam, (unsigned)h->tagqng_able); + + printk(" chip_scsi_id 0x%x, cfg 0x%lx\n", + (unsigned)h->chip_scsi_id, (ulong)h->cfg); } /* @@ -9289,26 +8068,21 @@ asc_prt_adv_dvc_var(ADV_DVC_VAR *h) * * Display an ADV_DVC_CFG structure. */ -STATIC void -asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) +static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) { - printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong) h); + printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h); - printk( -" disc_enable 0x%x, termination 0x%x\n", - h->disc_enable, h->termination); + printk(" disc_enable 0x%x, termination 0x%x\n", + h->disc_enable, h->termination); - printk( -" chip_version 0x%x, mcode_date 0x%x\n", - h->chip_version, h->mcode_date); + printk(" chip_version 0x%x, mcode_date 0x%x\n", + h->chip_version, h->mcode_date); - printk( -" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n", - h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version); + printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n", + h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version); - printk( -" control_flag 0x%x, pci_slot_info 0x%x\n", - h->control_flag, h->pci_slot_info); + printk(" control_flag 0x%x, pci_slot_info 0x%x\n", + h->control_flag, h->pci_slot_info); } /* @@ -9316,60 +8090,54 @@ asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) * * Display an ADV_SCSI_REQ_Q structure. */ -STATIC void -asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) +static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) { - int sg_blk_cnt; - struct asc_sg_block *sg_ptr; - - printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong) q); - - printk( -" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n", - q->target_id, q->target_lun, (ulong) q->srb_ptr, q->a_flag); - - printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n", - q->cntl, (ulong) le32_to_cpu(q->data_addr), (ulong) q->vdata_addr); - - printk( -" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", - (ulong) le32_to_cpu(q->data_cnt), - (ulong) le32_to_cpu(q->sense_addr), q->sense_len); - - printk( -" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n", - q->cdb_len, q->done_status, q->host_status, q->scsi_status); - - printk( -" sg_working_ix 0x%x, target_cmd %u\n", - q->sg_working_ix, q->target_cmd); - - printk( -" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n", - (ulong) le32_to_cpu(q->scsiq_rptr), - (ulong) le32_to_cpu(q->sg_real_addr), (ulong) q->sg_list_ptr); - - /* Display the request's ADV_SG_BLOCK structures. */ - if (q->sg_list_ptr != NULL) - { - sg_blk_cnt = 0; - while (1) { - /* - * 'sg_ptr' is a physical address. Convert it to a virtual - * address by indexing 'sg_blk_cnt' into the virtual address - * array 'sg_list_ptr'. - * - * XXX - Assumes all SG physical blocks are virtually contiguous. - */ - sg_ptr = &(((ADV_SG_BLOCK *) (q->sg_list_ptr))[sg_blk_cnt]); - asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr); - if (sg_ptr->sg_ptr == 0) - { - break; - } - sg_blk_cnt++; - } - } + int sg_blk_cnt; + struct asc_sg_block *sg_ptr; + + printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q); + + printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n", + q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag); + + printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n", + q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr); + + printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", + (ulong)le32_to_cpu(q->data_cnt), + (ulong)le32_to_cpu(q->sense_addr), q->sense_len); + + printk + (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n", + q->cdb_len, q->done_status, q->host_status, q->scsi_status); + + printk(" sg_working_ix 0x%x, target_cmd %u\n", + q->sg_working_ix, q->target_cmd); + + printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n", + (ulong)le32_to_cpu(q->scsiq_rptr), + (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr); + + /* Display the request's ADV_SG_BLOCK structures. */ + if (q->sg_list_ptr != NULL) { + sg_blk_cnt = 0; + while (1) { + /* + * 'sg_ptr' is a physical address. Convert it to a virtual + * address by indexing 'sg_blk_cnt' into the virtual address + * array 'sg_list_ptr'. + * + * XXX - Assumes all SG physical blocks are virtually contiguous. + */ + sg_ptr = + &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]); + asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr); + if (sg_ptr->sg_ptr == 0) { + break; + } + sg_blk_cnt++; + } + } } /* @@ -9377,24 +8145,23 @@ asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) * * Display an ADV_SG_BLOCK structure. */ -STATIC void -asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) +static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) { - int i; - - printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n", - (ulong) b, sgblockno); - printk(" sg_cnt %u, sg_ptr 0x%lx\n", - b->sg_cnt, (ulong) le32_to_cpu(b->sg_ptr)); - ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK); - if (b->sg_ptr != 0) - { - ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK); - } - for (i = 0; i < b->sg_cnt; i++) { - printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n", - i, (ulong) b->sg_list[i].sg_addr, (ulong) b->sg_list[i].sg_count); - } + int i; + + printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n", + (ulong)b, sgblockno); + printk(" sg_cnt %u, sg_ptr 0x%lx\n", + b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr)); + ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK); + if (b->sg_ptr != 0) { + ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK); + } + for (i = 0; i < b->sg_cnt; i++) { + printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n", + i, (ulong)b->sg_list[i].sg_addr, + (ulong)b->sg_list[i].sg_count); + } } /* @@ -9403,55 +8170,55 @@ asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) * Print hexadecimal output in 4 byte groupings 32 bytes * or 8 double-words per line. */ -STATIC void -asc_prt_hex(char *f, uchar *s, int l) +static void asc_prt_hex(char *f, uchar *s, int l) { - int i; - int j; - int k; - int m; - - printk("%s: (%d bytes)\n", f, l); - - for (i = 0; i < l; i += 32) { - - /* Display a maximum of 8 double-words per line. */ - if ((k = (l - i) / 4) >= 8) { - k = 8; - m = 0; - } else { - m = (l - i) % 4; - } - - for (j = 0; j < k; j++) { - printk(" %2.2X%2.2X%2.2X%2.2X", - (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1], - (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]); - } - - switch (m) { - case 0: - default: - break; - case 1: - printk(" %2.2X", - (unsigned) s[i+(j*4)]); - break; - case 2: - printk(" %2.2X%2.2X", - (unsigned) s[i+(j*4)], - (unsigned) s[i+(j*4)+1]); - break; - case 3: - printk(" %2.2X%2.2X%2.2X", - (unsigned) s[i+(j*4)+1], - (unsigned) s[i+(j*4)+2], - (unsigned) s[i+(j*4)+3]); - break; - } - - printk("\n"); - } + int i; + int j; + int k; + int m; + + printk("%s: (%d bytes)\n", f, l); + + for (i = 0; i < l; i += 32) { + + /* Display a maximum of 8 double-words per line. */ + if ((k = (l - i) / 4) >= 8) { + k = 8; + m = 0; + } else { + m = (l - i) % 4; + } + + for (j = 0; j < k; j++) { + printk(" %2.2X%2.2X%2.2X%2.2X", + (unsigned)s[i + (j * 4)], + (unsigned)s[i + (j * 4) + 1], + (unsigned)s[i + (j * 4) + 2], + (unsigned)s[i + (j * 4) + 3]); + } + + switch (m) { + case 0: + default: + break; + case 1: + printk(" %2.2X", (unsigned)s[i + (j * 4)]); + break; + case 2: + printk(" %2.2X%2.2X", + (unsigned)s[i + (j * 4)], + (unsigned)s[i + (j * 4) + 1]); + break; + case 3: + printk(" %2.2X%2.2X%2.2X", + (unsigned)s[i + (j * 4) + 1], + (unsigned)s[i + (j * 4) + 2], + (unsigned)s[i + (j * 4) + 3]); + break; + } + + printk("\n"); + } } #endif /* ADVANSYS_DEBUG */ @@ -9459,3380 +8226,3400 @@ asc_prt_hex(char *f, uchar *s, int l) * --- Asc Library Functions */ -STATIC ushort __init -AscGetEisaChipCfg( - PortAddr iop_base) +static ushort __init AscGetEisaChipCfg(PortAddr iop_base) { - PortAddr eisa_cfg_iop; + PortAddr eisa_cfg_iop; - eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | - (PortAddr) (ASC_EISA_CFG_IOP_MASK); - return (inpw(eisa_cfg_iop)); + eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | + (PortAddr) (ASC_EISA_CFG_IOP_MASK); + return (inpw(eisa_cfg_iop)); } -STATIC uchar __init -AscSetChipScsiID( - PortAddr iop_base, - uchar new_host_id -) +static uchar __init AscSetChipScsiID(PortAddr iop_base, uchar new_host_id) { - ushort cfg_lsw; + ushort cfg_lsw; - if (AscGetChipScsiID(iop_base) == new_host_id) { - return (new_host_id); - } - cfg_lsw = AscGetChipCfgLsw(iop_base); - cfg_lsw &= 0xF8FF; - cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8); - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetChipScsiID(iop_base)); + if (AscGetChipScsiID(iop_base) == new_host_id) { + return (new_host_id); + } + cfg_lsw = AscGetChipCfgLsw(iop_base); + cfg_lsw &= 0xF8FF; + cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8); + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetChipScsiID(iop_base)); } -STATIC uchar __init -AscGetChipScsiCtrl( - PortAddr iop_base) +static uchar __init AscGetChipScsiCtrl(PortAddr iop_base) { - uchar sc; + uchar sc; - AscSetBank(iop_base, 1); - sc = inp(iop_base + IOP_REG_SC); - AscSetBank(iop_base, 0); - return (sc); + AscSetBank(iop_base, 1); + sc = inp(iop_base + IOP_REG_SC); + AscSetBank(iop_base, 0); + return (sc); } -STATIC uchar __init -AscGetChipVersion( - PortAddr iop_base, - ushort bus_type -) +static uchar __init AscGetChipVersion(PortAddr iop_base, ushort bus_type) { - if ((bus_type & ASC_IS_EISA) != 0) { - PortAddr eisa_iop; - uchar revision; - eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | - (PortAddr) ASC_EISA_REV_IOP_MASK; - revision = inp(eisa_iop); - return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision)); - } - return (AscGetChipVerNo(iop_base)); + if ((bus_type & ASC_IS_EISA) != 0) { + PortAddr eisa_iop; + uchar revision; + eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | + (PortAddr) ASC_EISA_REV_IOP_MASK; + revision = inp(eisa_iop); + return ((uchar)((ASC_CHIP_MIN_VER_EISA - 1) + revision)); + } + return (AscGetChipVerNo(iop_base)); } -STATIC ushort __init -AscGetChipBusType( - PortAddr iop_base) +static ushort __init AscGetChipBusType(PortAddr iop_base) { - ushort chip_ver; - - chip_ver = AscGetChipVerNo(iop_base); - if ( - (chip_ver >= ASC_CHIP_MIN_VER_VL) - && (chip_ver <= ASC_CHIP_MAX_VER_VL) -) { - if ( - ((iop_base & 0x0C30) == 0x0C30) - || ((iop_base & 0x0C50) == 0x0C50) -) { - return (ASC_IS_EISA); - } - return (ASC_IS_VL); - } - if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) && - (chip_ver <= ASC_CHIP_MAX_VER_ISA)) { - if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) { - return (ASC_IS_ISAPNP); - } - return (ASC_IS_ISA); - } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) && - (chip_ver <= ASC_CHIP_MAX_VER_PCI)) { - return (ASC_IS_PCI); - } - return (0); + ushort chip_ver; + + chip_ver = AscGetChipVerNo(iop_base); + if ((chip_ver >= ASC_CHIP_MIN_VER_VL) + && (chip_ver <= ASC_CHIP_MAX_VER_VL) + ) { + if (((iop_base & 0x0C30) == 0x0C30) + || ((iop_base & 0x0C50) == 0x0C50) + ) { + return (ASC_IS_EISA); + } + return (ASC_IS_VL); + } + if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) && + (chip_ver <= ASC_CHIP_MAX_VER_ISA)) { + if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) { + return (ASC_IS_ISAPNP); + } + return (ASC_IS_ISA); + } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) && + (chip_ver <= ASC_CHIP_MAX_VER_PCI)) { + return (ASC_IS_PCI); + } + return (0); } -STATIC ASC_DCNT -AscLoadMicroCode( - PortAddr iop_base, - ushort s_addr, - uchar *mcode_buf, - ushort mcode_size -) +static ASC_DCNT +AscLoadMicroCode(PortAddr iop_base, + ushort s_addr, uchar *mcode_buf, ushort mcode_size) { - ASC_DCNT chksum; - ushort mcode_word_size; - ushort mcode_chksum; - - /* Write the microcode buffer starting at LRAM address 0. */ - mcode_word_size = (ushort) (mcode_size >> 1); - AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size); - AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size); - - chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size); - ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong) chksum); - mcode_chksum = (ushort) AscMemSumLramWord(iop_base, - (ushort) ASC_CODE_SEC_BEG, - (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2)); - ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n", - (ulong) mcode_chksum); - AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum); - AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size); - return (chksum); + ASC_DCNT chksum; + ushort mcode_word_size; + ushort mcode_chksum; + + /* Write the microcode buffer starting at LRAM address 0. */ + mcode_word_size = (ushort)(mcode_size >> 1); + AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size); + AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size); + + chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size); + ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum); + mcode_chksum = (ushort)AscMemSumLramWord(iop_base, + (ushort)ASC_CODE_SEC_BEG, + (ushort)((mcode_size - + s_addr - (ushort) + ASC_CODE_SEC_BEG) / + 2)); + ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n", + (ulong)mcode_chksum); + AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum); + AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size); + return (chksum); } -STATIC int -AscFindSignature( - PortAddr iop_base -) +static int AscFindSignature(PortAddr iop_base) { - ushort sig_word; - - ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n", - iop_base, AscGetChipSignatureByte(iop_base)); - if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) { - ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n", - iop_base, AscGetChipSignatureWord(iop_base)); - sig_word = AscGetChipSignatureWord(iop_base); - if ((sig_word == (ushort) ASC_1000_ID0W) || - (sig_word == (ushort) ASC_1000_ID0W_FIX)) { - return (1); - } - } - return (0); + ushort sig_word; + + ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n", + iop_base, AscGetChipSignatureByte(iop_base)); + if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) { + ASC_DBG2(1, + "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n", + iop_base, AscGetChipSignatureWord(iop_base)); + sig_word = AscGetChipSignatureWord(iop_base); + if ((sig_word == (ushort)ASC_1000_ID0W) || + (sig_word == (ushort)ASC_1000_ID0W_FIX)) { + return (1); + } + } + return (0); } -STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __initdata = -{ - 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4, - ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8 +static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __initdata = { + 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4, + ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8 }; #ifdef CONFIG_ISA -STATIC uchar _isa_pnp_inited __initdata = 0; +static uchar _isa_pnp_inited __initdata = 0; -STATIC PortAddr __init -AscSearchIOPortAddr( - PortAddr iop_beg, - ushort bus_type) +static PortAddr __init AscSearchIOPortAddr(PortAddr iop_beg, ushort bus_type) { - if (bus_type & ASC_IS_VL) { - while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { - if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) { - return (iop_beg); - } - } - return (0); - } - if (bus_type & ASC_IS_ISA) { - if (_isa_pnp_inited == 0) { - AscSetISAPNPWaitForKey(); - _isa_pnp_inited++; - } - while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { - if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) { - return (iop_beg); - } - } - return (0); - } - if (bus_type & ASC_IS_EISA) { - if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) { - return (iop_beg); - } - return (0); - } - return (0); + if (bus_type & ASC_IS_VL) { + while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { + if (AscGetChipVersion(iop_beg, bus_type) <= + ASC_CHIP_MAX_VER_VL) { + return (iop_beg); + } + } + return (0); + } + if (bus_type & ASC_IS_ISA) { + if (_isa_pnp_inited == 0) { + AscSetISAPNPWaitForKey(); + _isa_pnp_inited++; + } + while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { + if ((AscGetChipVersion(iop_beg, bus_type) & + ASC_CHIP_VER_ISA_BIT) != 0) { + return (iop_beg); + } + } + return (0); + } + if (bus_type & ASC_IS_EISA) { + if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) { + return (iop_beg); + } + return (0); + } + return (0); } -STATIC PortAddr __init -AscSearchIOPortAddr11( - PortAddr s_addr -) +static PortAddr __init AscSearchIOPortAddr11(PortAddr s_addr) { - int i; - PortAddr iop_base; + int i; + PortAddr iop_base; - for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) { - if (_asc_def_iop_base[i] > s_addr) { - break; - } - } - for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { - iop_base = _asc_def_iop_base[i]; - 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); - } - } - return (0); + for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) { + if (_asc_def_iop_base[i] > s_addr) { + break; + } + } + for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { + iop_base = _asc_def_iop_base[i]; + 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); + } + } + return (0); } -STATIC void __init -AscSetISAPNPWaitForKey(void) +static void __init AscSetISAPNPWaitForKey(void) { - outp(ASC_ISA_PNP_PORT_ADDR, 0x02); - outp(ASC_ISA_PNP_PORT_WRITE, 0x02); - return; + outp(ASC_ISA_PNP_PORT_ADDR, 0x02); + outp(ASC_ISA_PNP_PORT_WRITE, 0x02); + return; } #endif /* CONFIG_ISA */ -STATIC void __init -AscToggleIRQAct( - PortAddr iop_base -) +static void __init AscToggleIRQAct(PortAddr iop_base) { - AscSetChipStatus(iop_base, CIW_IRQ_ACT); - AscSetChipStatus(iop_base, 0); - return; + AscSetChipStatus(iop_base, CIW_IRQ_ACT); + AscSetChipStatus(iop_base, 0); + return; } -STATIC uchar __init -AscGetChipIRQ( - PortAddr iop_base, - ushort bus_type) +static uchar __init AscGetChipIRQ(PortAddr iop_base, ushort bus_type) { - ushort cfg_lsw; - uchar chip_irq; - - if ((bus_type & ASC_IS_EISA) != 0) { - cfg_lsw = AscGetEisaChipCfg(iop_base); - chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10); - if ((chip_irq == 13) || (chip_irq > 15)) { - return (0); - } - return (chip_irq); - } - if ((bus_type & ASC_IS_VL) != 0) { - cfg_lsw = AscGetChipCfgLsw(iop_base); - chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07)); - if ((chip_irq == 0) || - (chip_irq == 4) || - (chip_irq == 7)) { - return (0); - } - return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1))); - } - cfg_lsw = AscGetChipCfgLsw(iop_base); - chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03)); - if (chip_irq == 3) - chip_irq += (uchar) 2; - return ((uchar) (chip_irq + ASC_MIN_IRQ_NO)); + ushort cfg_lsw; + uchar chip_irq; + + if ((bus_type & ASC_IS_EISA) != 0) { + cfg_lsw = AscGetEisaChipCfg(iop_base); + chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10); + if ((chip_irq == 13) || (chip_irq > 15)) { + return (0); + } + return (chip_irq); + } + if ((bus_type & ASC_IS_VL) != 0) { + cfg_lsw = AscGetChipCfgLsw(iop_base); + chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07)); + if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) { + return (0); + } + return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1))); + } + cfg_lsw = AscGetChipCfgLsw(iop_base); + chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03)); + if (chip_irq == 3) + chip_irq += (uchar)2; + return ((uchar)(chip_irq + ASC_MIN_IRQ_NO)); } -STATIC uchar __init -AscSetChipIRQ( - PortAddr iop_base, - uchar irq_no, - ushort bus_type) +static uchar __init +AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type) { - ushort cfg_lsw; - - if ((bus_type & ASC_IS_VL) != 0) { - if (irq_no != 0) { - if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) { - irq_no = 0; - } else { - irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1)); - } - } - cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3); - cfg_lsw |= (ushort) 0x0010; - AscSetChipCfgLsw(iop_base, cfg_lsw); - AscToggleIRQAct(iop_base); - cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0); - cfg_lsw |= (ushort) ((irq_no & 0x07) << 2); - AscSetChipCfgLsw(iop_base, cfg_lsw); - AscToggleIRQAct(iop_base); - return (AscGetChipIRQ(iop_base, bus_type)); - } - if ((bus_type & (ASC_IS_ISA)) != 0) { - if (irq_no == 15) - irq_no -= (uchar) 2; - irq_no -= (uchar) ASC_MIN_IRQ_NO; - cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3); - cfg_lsw |= (ushort) ((irq_no & 0x03) << 2); - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetChipIRQ(iop_base, bus_type)); - } - return (0); + ushort cfg_lsw; + + if ((bus_type & ASC_IS_VL) != 0) { + if (irq_no != 0) { + if ((irq_no < ASC_MIN_IRQ_NO) + || (irq_no > ASC_MAX_IRQ_NO)) { + irq_no = 0; + } else { + irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1)); + } + } + cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3); + cfg_lsw |= (ushort)0x0010; + AscSetChipCfgLsw(iop_base, cfg_lsw); + AscToggleIRQAct(iop_base); + cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0); + cfg_lsw |= (ushort)((irq_no & 0x07) << 2); + AscSetChipCfgLsw(iop_base, cfg_lsw); + AscToggleIRQAct(iop_base); + return (AscGetChipIRQ(iop_base, bus_type)); + } + if ((bus_type & (ASC_IS_ISA)) != 0) { + if (irq_no == 15) + irq_no -= (uchar)2; + irq_no -= (uchar)ASC_MIN_IRQ_NO; + cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3); + cfg_lsw |= (ushort)((irq_no & 0x03) << 2); + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetChipIRQ(iop_base, bus_type)); + } + return (0); } #ifdef CONFIG_ISA -STATIC void __init -AscEnableIsaDma( - uchar dma_channel) +static void __init AscEnableIsaDma(uchar dma_channel) { - if (dma_channel < 4) { - outp(0x000B, (ushort) (0xC0 | dma_channel)); - outp(0x000A, dma_channel); - } else if (dma_channel < 8) { - outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4))); - outp(0x00D4, (ushort) (dma_channel - 4)); - } - return; + if (dma_channel < 4) { + outp(0x000B, (ushort)(0xC0 | dma_channel)); + outp(0x000A, dma_channel); + } else if (dma_channel < 8) { + outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4))); + outp(0x00D4, (ushort)(dma_channel - 4)); + } + return; } #endif /* CONFIG_ISA */ -STATIC int -AscIsrChipHalted( - ASC_DVC_VAR *asc_dvc -) +static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) { - EXT_MSG ext_msg; - EXT_MSG out_msg; - ushort halt_q_addr; - int sdtr_accept; - ushort int_halt_code; - ASC_SCSI_BIT_ID_TYPE scsi_busy; - ASC_SCSI_BIT_ID_TYPE target_id; - PortAddr iop_base; - uchar tag_code; - uchar q_status; - uchar halt_qp; - uchar sdtr_data; - uchar target_ix; - uchar q_cntl, tid_no; - uchar cur_dvc_qng; - uchar asyn_sdtr; - uchar scsi_status; - asc_board_t *boardp; - - ASC_ASSERT(asc_dvc->drv_ptr != NULL); - boardp = asc_dvc->drv_ptr; - - iop_base = asc_dvc->iop_base; - int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); - - halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); - halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); - target_ix = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX)); - q_cntl = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL)); - tid_no = ASC_TIX_TO_TID(target_ix); - target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no); - if (asc_dvc->pci_fix_asyn_xfer & target_id) { - asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB; - } else { - asyn_sdtr = 0; - } - if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) { - if (asc_dvc->pci_fix_asyn_xfer & target_id) { - AscSetChipSDTR(iop_base, 0, tid_no); - boardp->sdtr_data[tid_no] = 0; - } - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) { - if (asc_dvc->pci_fix_asyn_xfer & target_id) { - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - boardp->sdtr_data[tid_no] = asyn_sdtr; - } - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_EXTMSG_IN) { - - AscMemWordCopyPtrFromLram(iop_base, - ASCV_MSGIN_BEG, - (uchar *) &ext_msg, - sizeof(EXT_MSG) >> 1); - - if (ext_msg.msg_type == MS_EXTEND && - ext_msg.msg_req == MS_SDTR_CODE && - ext_msg.msg_len == MS_SDTR_LEN) { - sdtr_accept = TRUE; - if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) { - - sdtr_accept = FALSE; - ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET; - } - if ((ext_msg.xfer_period < - asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]) || - (ext_msg.xfer_period > - asc_dvc->sdtr_period_tbl[asc_dvc->max_sdtr_index])) { - sdtr_accept = FALSE; - ext_msg.xfer_period = - asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]; - } - if (sdtr_accept) { - sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period, - ext_msg.req_ack_offset); - if ((sdtr_data == 0xFF)) { - - q_cntl |= QC_MSG_OUT; - asc_dvc->init_sdtr &= ~target_id; - asc_dvc->sdtr_done &= ~target_id; - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - boardp->sdtr_data[tid_no] = asyn_sdtr; - } - } - if (ext_msg.req_ack_offset == 0) { - - q_cntl &= ~QC_MSG_OUT; - asc_dvc->init_sdtr &= ~target_id; - asc_dvc->sdtr_done &= ~target_id; - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - } else { - if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { - - q_cntl &= ~QC_MSG_OUT; - asc_dvc->sdtr_done |= target_id; - asc_dvc->init_sdtr |= target_id; - asc_dvc->pci_fix_asyn_xfer &= ~target_id; - sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period, - ext_msg.req_ack_offset); - AscSetChipSDTR(iop_base, sdtr_data, tid_no); - boardp->sdtr_data[tid_no] = sdtr_data; - } else { - - q_cntl |= QC_MSG_OUT; - AscMsgOutSDTR(asc_dvc, - ext_msg.xfer_period, - ext_msg.req_ack_offset); - asc_dvc->pci_fix_asyn_xfer &= ~target_id; - sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period, - ext_msg.req_ack_offset); - AscSetChipSDTR(iop_base, sdtr_data, tid_no); - boardp->sdtr_data[tid_no] = sdtr_data; - asc_dvc->sdtr_done |= target_id; - asc_dvc->init_sdtr |= target_id; - } - } - - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (ext_msg.msg_type == MS_EXTEND && - ext_msg.msg_req == MS_WDTR_CODE && - ext_msg.msg_len == MS_WDTR_LEN) { - - ext_msg.wdtr_width = 0; - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &ext_msg, - sizeof(EXT_MSG) >> 1); - q_cntl |= QC_MSG_OUT; - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else { - - ext_msg.msg_type = MESSAGE_REJECT; - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &ext_msg, - sizeof(EXT_MSG) >> 1); - q_cntl |= QC_MSG_OUT; - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } - } else if (int_halt_code == ASC_HALT_CHK_CONDITION) { - - q_cntl |= QC_REQ_SENSE; - - if ((asc_dvc->init_sdtr & target_id) != 0) { - - asc_dvc->sdtr_done &= ~target_id; - - sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); - q_cntl |= QC_MSG_OUT; - AscMsgOutSDTR(asc_dvc, - asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) & - (uchar) (asc_dvc->max_sdtr_index - 1)], - (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); - } - - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - - tag_code = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE)); - tag_code &= 0xDC; - if ( - (asc_dvc->pci_fix_asyn_xfer & target_id) - && !(asc_dvc->pci_fix_asyn_xfer_always & target_id) -) { - - tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT - | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX); - - } - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE), - tag_code); - - q_status = AscReadLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS)); - q_status |= (QS_READY | QS_BUSY); - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS), - q_status); - - scsi_busy = AscReadLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B); - scsi_busy &= ~target_id; - AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy); - - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) { - - AscMemWordCopyPtrFromLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &out_msg, - sizeof(EXT_MSG) >> 1); - - if ((out_msg.msg_type == MS_EXTEND) && - (out_msg.msg_len == MS_SDTR_LEN) && - (out_msg.msg_req == MS_SDTR_CODE)) { - - asc_dvc->init_sdtr &= ~target_id; - asc_dvc->sdtr_done &= ~target_id; - AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); - boardp->sdtr_data[tid_no] = asyn_sdtr; - } - q_cntl &= ~QC_MSG_OUT; - AscWriteLramByte(iop_base, - (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), - q_cntl); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) { - - scsi_status = AscReadLramByte(iop_base, - (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS)); - cur_dvc_qng = AscReadLramByte(iop_base, - (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix)); - if ((cur_dvc_qng > 0) && - (asc_dvc->cur_dvc_qng[tid_no] > 0)) { - - scsi_busy = AscReadLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B); - scsi_busy |= target_id; - AscWriteLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B, scsi_busy); - asc_dvc->queue_full_or_busy |= target_id; - - if (scsi_status == SAM_STAT_TASK_SET_FULL) { - if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { - cur_dvc_qng -= 1; - asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng; - - AscWriteLramByte(iop_base, - (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + - (ushort) tid_no), - cur_dvc_qng); - - /* - * Set the device queue depth to the number of - * active requests when the QUEUE FULL condition - * was encountered. - */ - boardp->queue_full |= target_id; - boardp->queue_full_cnt[tid_no] = cur_dvc_qng; - } - } - } - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return (0); - } + EXT_MSG ext_msg; + EXT_MSG out_msg; + ushort halt_q_addr; + int sdtr_accept; + ushort int_halt_code; + ASC_SCSI_BIT_ID_TYPE scsi_busy; + ASC_SCSI_BIT_ID_TYPE target_id; + PortAddr iop_base; + uchar tag_code; + uchar q_status; + uchar halt_qp; + uchar sdtr_data; + uchar target_ix; + uchar q_cntl, tid_no; + uchar cur_dvc_qng; + uchar asyn_sdtr; + uchar scsi_status; + asc_board_t *boardp; + + ASC_ASSERT(asc_dvc->drv_ptr != NULL); + boardp = asc_dvc->drv_ptr; + + iop_base = asc_dvc->iop_base; + int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); + + halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); + halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); + target_ix = AscReadLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_TARGET_IX)); + q_cntl = + AscReadLramByte(iop_base, + (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL)); + tid_no = ASC_TIX_TO_TID(target_ix); + target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no); + if (asc_dvc->pci_fix_asyn_xfer & target_id) { + asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB; + } else { + asyn_sdtr = 0; + } + if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) { + if (asc_dvc->pci_fix_asyn_xfer & target_id) { + AscSetChipSDTR(iop_base, 0, tid_no); + boardp->sdtr_data[tid_no] = 0; + } + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) { + if (asc_dvc->pci_fix_asyn_xfer & target_id) { + AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); + boardp->sdtr_data[tid_no] = asyn_sdtr; + } + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_EXTMSG_IN) { + + AscMemWordCopyPtrFromLram(iop_base, + ASCV_MSGIN_BEG, + (uchar *)&ext_msg, + sizeof(EXT_MSG) >> 1); + + if (ext_msg.msg_type == MS_EXTEND && + ext_msg.msg_req == MS_SDTR_CODE && + ext_msg.msg_len == MS_SDTR_LEN) { + sdtr_accept = TRUE; + if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) { + + sdtr_accept = FALSE; + ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET; + } + if ((ext_msg.xfer_period < + asc_dvc->sdtr_period_tbl[asc_dvc-> + host_init_sdtr_index]) + || (ext_msg.xfer_period > + asc_dvc->sdtr_period_tbl[asc_dvc-> + max_sdtr_index])) { + sdtr_accept = FALSE; + ext_msg.xfer_period = + asc_dvc->sdtr_period_tbl[asc_dvc-> + host_init_sdtr_index]; + } + if (sdtr_accept) { + sdtr_data = + AscCalSDTRData(asc_dvc, ext_msg.xfer_period, + ext_msg.req_ack_offset); + if ((sdtr_data == 0xFF)) { + + q_cntl |= QC_MSG_OUT; + asc_dvc->init_sdtr &= ~target_id; + asc_dvc->sdtr_done &= ~target_id; + AscSetChipSDTR(iop_base, asyn_sdtr, + tid_no); + boardp->sdtr_data[tid_no] = asyn_sdtr; + } + } + if (ext_msg.req_ack_offset == 0) { + + q_cntl &= ~QC_MSG_OUT; + asc_dvc->init_sdtr &= ~target_id; + asc_dvc->sdtr_done &= ~target_id; + AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); + } else { + if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { + + q_cntl &= ~QC_MSG_OUT; + asc_dvc->sdtr_done |= target_id; + asc_dvc->init_sdtr |= target_id; + asc_dvc->pci_fix_asyn_xfer &= + ~target_id; + sdtr_data = + AscCalSDTRData(asc_dvc, + ext_msg.xfer_period, + ext_msg. + req_ack_offset); + AscSetChipSDTR(iop_base, sdtr_data, + tid_no); + boardp->sdtr_data[tid_no] = sdtr_data; + } else { + + q_cntl |= QC_MSG_OUT; + AscMsgOutSDTR(asc_dvc, + ext_msg.xfer_period, + ext_msg.req_ack_offset); + asc_dvc->pci_fix_asyn_xfer &= + ~target_id; + sdtr_data = + AscCalSDTRData(asc_dvc, + ext_msg.xfer_period, + ext_msg. + req_ack_offset); + AscSetChipSDTR(iop_base, sdtr_data, + tid_no); + boardp->sdtr_data[tid_no] = sdtr_data; + asc_dvc->sdtr_done |= target_id; + asc_dvc->init_sdtr |= target_id; + } + } + + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), + q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (ext_msg.msg_type == MS_EXTEND && + ext_msg.msg_req == MS_WDTR_CODE && + ext_msg.msg_len == MS_WDTR_LEN) { + + ext_msg.wdtr_width = 0; + AscMemWordCopyPtrToLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&ext_msg, + sizeof(EXT_MSG) >> 1); + q_cntl |= QC_MSG_OUT; + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), + q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else { + + ext_msg.msg_type = MESSAGE_REJECT; + AscMemWordCopyPtrToLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&ext_msg, + sizeof(EXT_MSG) >> 1); + q_cntl |= QC_MSG_OUT; + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), + q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } + } else if (int_halt_code == ASC_HALT_CHK_CONDITION) { + + q_cntl |= QC_REQ_SENSE; + + if ((asc_dvc->init_sdtr & target_id) != 0) { + + asc_dvc->sdtr_done &= ~target_id; + + sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); + q_cntl |= QC_MSG_OUT; + AscMsgOutSDTR(asc_dvc, + asc_dvc-> + sdtr_period_tbl[(sdtr_data >> 4) & + (uchar)(asc_dvc-> + max_sdtr_index - + 1)], + (uchar)(sdtr_data & (uchar) + ASC_SYN_MAX_OFFSET)); + } + + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), q_cntl); + + tag_code = AscReadLramByte(iop_base, + (ushort)(halt_q_addr + (ushort) + ASC_SCSIQ_B_TAG_CODE)); + tag_code &= 0xDC; + if ((asc_dvc->pci_fix_asyn_xfer & target_id) + && !(asc_dvc->pci_fix_asyn_xfer_always & target_id) + ) { + + tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT + | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX); + + } + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_TAG_CODE), + tag_code); + + q_status = AscReadLramByte(iop_base, + (ushort)(halt_q_addr + (ushort) + ASC_SCSIQ_B_STATUS)); + q_status |= (QS_READY | QS_BUSY); + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_STATUS), + q_status); + + scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B); + scsi_busy &= ~target_id; + AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy); + + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) { + + AscMemWordCopyPtrFromLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&out_msg, + sizeof(EXT_MSG) >> 1); + + if ((out_msg.msg_type == MS_EXTEND) && + (out_msg.msg_len == MS_SDTR_LEN) && + (out_msg.msg_req == MS_SDTR_CODE)) { + + asc_dvc->init_sdtr &= ~target_id; + asc_dvc->sdtr_done &= ~target_id; + AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); + boardp->sdtr_data[tid_no] = asyn_sdtr; + } + q_cntl &= ~QC_MSG_OUT; + AscWriteLramByte(iop_base, + (ushort)(halt_q_addr + + (ushort)ASC_SCSIQ_B_CNTL), q_cntl); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) { + + scsi_status = AscReadLramByte(iop_base, + (ushort)((ushort)halt_q_addr + + (ushort) + ASC_SCSIQ_SCSI_STATUS)); + cur_dvc_qng = + AscReadLramByte(iop_base, + (ushort)((ushort)ASC_QADR_BEG + + (ushort)target_ix)); + if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) { + + scsi_busy = AscReadLramByte(iop_base, + (ushort)ASCV_SCSIBUSY_B); + scsi_busy |= target_id; + AscWriteLramByte(iop_base, + (ushort)ASCV_SCSIBUSY_B, scsi_busy); + asc_dvc->queue_full_or_busy |= target_id; + + if (scsi_status == SAM_STAT_TASK_SET_FULL) { + if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { + cur_dvc_qng -= 1; + asc_dvc->max_dvc_qng[tid_no] = + cur_dvc_qng; + + AscWriteLramByte(iop_base, + (ushort)((ushort) + ASCV_MAX_DVC_QNG_BEG + + (ushort) + tid_no), + cur_dvc_qng); + + /* + * Set the device queue depth to the number of + * active requests when the QUEUE FULL condition + * was encountered. + */ + boardp->queue_full |= target_id; + boardp->queue_full_cnt[tid_no] = + cur_dvc_qng; + } + } + } + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } #if CC_VERY_LONG_SG_LIST - else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) - { - uchar q_no; - ushort q_addr; - uchar sg_wk_q_no; - uchar first_sg_wk_q_no; - ASC_SCSI_Q *scsiq; /* Ptr to driver request. */ - ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */ - ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */ - ushort sg_list_dwords; - ushort sg_entry_cnt; - uchar next_qp; - int i; - - q_no = AscReadLramByte(iop_base, (ushort) ASCV_REQ_SG_LIST_QP); - if (q_no == ASC_QLINK_END) - { - return(0); - } - - q_addr = ASC_QNO_TO_QADDR(q_no); - - /* - * Convert the request's SRB pointer to a host ASC_SCSI_REQ - * structure pointer using a macro provided by the driver. - * The ASC_SCSI_REQ pointer provides a pointer to the - * host ASC_SG_HEAD structure. - */ - /* Read request's SRB pointer. */ - scsiq = (ASC_SCSI_Q *) - ASC_SRB2SCSIQ( - ASC_U32_TO_VADDR(AscReadLramDWord(iop_base, - (ushort) (q_addr + ASC_SCSIQ_D_SRBPTR)))); - - /* - * Get request's first and working SG queue. - */ - sg_wk_q_no = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_SG_WK_QP)); - - first_sg_wk_q_no = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_FIRST_SG_WK_QP)); - - /* - * Reset request's working SG queue back to the - * first SG queue. - */ - AscWriteLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SG_WK_QP), - first_sg_wk_q_no); - - sg_head = scsiq->sg_head; - - /* - * Set sg_entry_cnt to the number of SG elements - * that will be completed on this interrupt. - * - * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1 - * SG elements. The data_cnt and data_addr fields which - * add 1 to the SG element capacity are not used when - * restarting SG handling after a halt. - */ - if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) - { - sg_entry_cnt = ASC_MAX_SG_LIST - 1; - - /* - * Keep track of remaining number of SG elements that will - * need to be handled on the next interrupt. - */ - scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1); - } else - { - sg_entry_cnt = scsiq->remain_sg_entry_cnt; - scsiq->remain_sg_entry_cnt = 0; - } - - /* - * Copy SG elements into the list of allocated SG queues. - * - * Last index completed is saved in scsiq->next_sg_index. - */ - next_qp = first_sg_wk_q_no; - q_addr = ASC_QNO_TO_QADDR(next_qp); - scsi_sg_q.sg_head_qp = q_no; - scsi_sg_q.cntl = QCSG_SG_XFER_LIST; - for( i = 0; i < sg_head->queue_cnt; i++) - { - scsi_sg_q.seq_no = i + 1; - if (sg_entry_cnt > ASC_SG_LIST_PER_Q) - { - sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2); - sg_entry_cnt -= ASC_SG_LIST_PER_Q; - /* - * After very first SG queue RISC FW uses next - * SG queue first element then checks sg_list_cnt - * against zero and then decrements, so set - * sg_list_cnt 1 less than number of SG elements - * in each SG queue. - */ - scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; - scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1; - } else { - /* - * This is the last SG queue in the list of - * allocated SG queues. If there are more - * SG elements than will fit in the allocated - * queues, then set the QCSG_SG_XFER_MORE flag. - */ - if (scsiq->remain_sg_entry_cnt != 0) - { - scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; - } else - { - scsi_sg_q.cntl |= QCSG_SG_XFER_END; - } - /* equals sg_entry_cnt * 2 */ - sg_list_dwords = sg_entry_cnt << 1; - scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; - scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; - sg_entry_cnt = 0; - } - - scsi_sg_q.q_no = next_qp; - AscMemWordCopyPtrToLram(iop_base, - q_addr + ASC_SCSIQ_SGHD_CPY_BEG, - (uchar *) &scsi_sg_q, - sizeof(ASC_SG_LIST_Q) >> 1); - - AscMemDWordCopyPtrToLram(iop_base, - q_addr + ASC_SGQ_LIST_BEG, - (uchar *) &sg_head->sg_list[scsiq->next_sg_index], - sg_list_dwords); - - scsiq->next_sg_index += ASC_SG_LIST_PER_Q; - - /* - * If the just completed SG queue contained the - * last SG element, then no more SG queues need - * to be written. - */ - if (scsi_sg_q.cntl & QCSG_SG_XFER_END) - { - break; - } - - next_qp = AscReadLramByte( iop_base, - ( ushort )( q_addr+ASC_SCSIQ_B_FWD ) ); - q_addr = ASC_QNO_TO_QADDR( next_qp ); - } - - /* - * Clear the halt condition so the RISC will be restarted - * after the return. - */ - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - return(0); - } + else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) { + uchar q_no; + ushort q_addr; + uchar sg_wk_q_no; + uchar first_sg_wk_q_no; + ASC_SCSI_Q *scsiq; /* Ptr to driver request. */ + ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */ + ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */ + ushort sg_list_dwords; + ushort sg_entry_cnt; + uchar next_qp; + int i; + + q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP); + if (q_no == ASC_QLINK_END) { + return (0); + } + + q_addr = ASC_QNO_TO_QADDR(q_no); + + /* + * Convert the request's SRB pointer to a host ASC_SCSI_REQ + * structure pointer using a macro provided by the driver. + * The ASC_SCSI_REQ pointer provides a pointer to the + * host ASC_SG_HEAD structure. + */ + /* Read request's SRB pointer. */ + scsiq = (ASC_SCSI_Q *) + ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base, + (ushort) + (q_addr + + ASC_SCSIQ_D_SRBPTR)))); + + /* + * Get request's first and working SG queue. + */ + sg_wk_q_no = AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_SG_WK_QP)); + + first_sg_wk_q_no = AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_FIRST_SG_WK_QP)); + + /* + * Reset request's working SG queue back to the + * first SG queue. + */ + AscWriteLramByte(iop_base, + (ushort)(q_addr + + (ushort)ASC_SCSIQ_B_SG_WK_QP), + first_sg_wk_q_no); + + sg_head = scsiq->sg_head; + + /* + * Set sg_entry_cnt to the number of SG elements + * that will be completed on this interrupt. + * + * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1 + * SG elements. The data_cnt and data_addr fields which + * add 1 to the SG element capacity are not used when + * restarting SG handling after a halt. + */ + if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) { + sg_entry_cnt = ASC_MAX_SG_LIST - 1; + + /* + * Keep track of remaining number of SG elements that will + * need to be handled on the next interrupt. + */ + scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1); + } else { + sg_entry_cnt = scsiq->remain_sg_entry_cnt; + scsiq->remain_sg_entry_cnt = 0; + } + + /* + * Copy SG elements into the list of allocated SG queues. + * + * Last index completed is saved in scsiq->next_sg_index. + */ + next_qp = first_sg_wk_q_no; + q_addr = ASC_QNO_TO_QADDR(next_qp); + scsi_sg_q.sg_head_qp = q_no; + scsi_sg_q.cntl = QCSG_SG_XFER_LIST; + for (i = 0; i < sg_head->queue_cnt; i++) { + scsi_sg_q.seq_no = i + 1; + if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { + sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); + sg_entry_cnt -= ASC_SG_LIST_PER_Q; + /* + * After very first SG queue RISC FW uses next + * SG queue first element then checks sg_list_cnt + * against zero and then decrements, so set + * sg_list_cnt 1 less than number of SG elements + * in each SG queue. + */ + scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; + scsi_sg_q.sg_cur_list_cnt = + ASC_SG_LIST_PER_Q - 1; + } else { + /* + * This is the last SG queue in the list of + * allocated SG queues. If there are more + * SG elements than will fit in the allocated + * queues, then set the QCSG_SG_XFER_MORE flag. + */ + if (scsiq->remain_sg_entry_cnt != 0) { + scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; + } else { + scsi_sg_q.cntl |= QCSG_SG_XFER_END; + } + /* equals sg_entry_cnt * 2 */ + sg_list_dwords = sg_entry_cnt << 1; + scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; + scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; + sg_entry_cnt = 0; + } + + scsi_sg_q.q_no = next_qp; + AscMemWordCopyPtrToLram(iop_base, + q_addr + ASC_SCSIQ_SGHD_CPY_BEG, + (uchar *)&scsi_sg_q, + sizeof(ASC_SG_LIST_Q) >> 1); + + AscMemDWordCopyPtrToLram(iop_base, + q_addr + ASC_SGQ_LIST_BEG, + (uchar *)&sg_head-> + sg_list[scsiq->next_sg_index], + sg_list_dwords); + + scsiq->next_sg_index += ASC_SG_LIST_PER_Q; + + /* + * If the just completed SG queue contained the + * last SG element, then no more SG queues need + * to be written. + */ + if (scsi_sg_q.cntl & QCSG_SG_XFER_END) { + break; + } + + next_qp = AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_FWD)); + q_addr = ASC_QNO_TO_QADDR(next_qp); + } + + /* + * Clear the halt condition so the RISC will be restarted + * after the return. + */ + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + return (0); + } #endif /* CC_VERY_LONG_SG_LIST */ - return (0); + return (0); } -STATIC uchar -_AscCopyLramScsiDoneQ( - PortAddr iop_base, - ushort q_addr, - ASC_QDONE_INFO * scsiq, - ASC_DCNT max_dma_count -) +static uchar +_AscCopyLramScsiDoneQ(PortAddr iop_base, + ushort q_addr, + ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count) { - ushort _val; - uchar sg_queue_cnt; - - DvcGetQinfo(iop_base, - q_addr + ASC_SCSIQ_DONE_INFO_BEG, - (uchar *) scsiq, - (sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2); - - _val = AscReadLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS)); - scsiq->q_status = (uchar) _val; - scsiq->q_no = (uchar) (_val >> 8); - _val = AscReadLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL)); - scsiq->cntl = (uchar) _val; - sg_queue_cnt = (uchar) (_val >> 8); - _val = AscReadLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN)); - scsiq->sense_len = (uchar) _val; - scsiq->extra_bytes = (uchar) (_val >> 8); - - /* - * Read high word of remain bytes from alternate location. - */ - scsiq->remain_bytes = (((ADV_DCNT) AscReadLramWord( iop_base, - (ushort) (q_addr+ (ushort) ASC_SCSIQ_W_ALT_DC1))) << 16); - /* - * Read low word of remain bytes from original location. - */ - scsiq->remain_bytes += AscReadLramWord(iop_base, - (ushort) (q_addr+ (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT)); - - scsiq->remain_bytes &= max_dma_count; - return (sg_queue_cnt); + ushort _val; + uchar sg_queue_cnt; + + DvcGetQinfo(iop_base, + q_addr + ASC_SCSIQ_DONE_INFO_BEG, + (uchar *)scsiq, + (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2); + + _val = AscReadLramWord(iop_base, + (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS)); + scsiq->q_status = (uchar)_val; + scsiq->q_no = (uchar)(_val >> 8); + _val = AscReadLramWord(iop_base, + (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL)); + scsiq->cntl = (uchar)_val; + sg_queue_cnt = (uchar)(_val >> 8); + _val = AscReadLramWord(iop_base, + (ushort)(q_addr + + (ushort)ASC_SCSIQ_B_SENSE_LEN)); + scsiq->sense_len = (uchar)_val; + scsiq->extra_bytes = (uchar)(_val >> 8); + + /* + * Read high word of remain bytes from alternate location. + */ + scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base, + (ushort)(q_addr + + (ushort) + ASC_SCSIQ_W_ALT_DC1))) + << 16); + /* + * Read low word of remain bytes from original location. + */ + scsiq->remain_bytes += AscReadLramWord(iop_base, + (ushort)(q_addr + (ushort) + ASC_SCSIQ_DW_REMAIN_XFER_CNT)); + + scsiq->remain_bytes &= max_dma_count; + return (sg_queue_cnt); } -STATIC int -AscIsrQDone( - ASC_DVC_VAR *asc_dvc -) +static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) { - uchar next_qp; - uchar n_q_used; - uchar sg_list_qp; - uchar sg_queue_cnt; - uchar q_cnt; - uchar done_q_tail; - uchar tid_no; - ASC_SCSI_BIT_ID_TYPE scsi_busy; - ASC_SCSI_BIT_ID_TYPE target_id; - PortAddr iop_base; - ushort q_addr; - ushort sg_q_addr; - uchar cur_target_qng; - ASC_QDONE_INFO scsiq_buf; - ASC_QDONE_INFO *scsiq; - int false_overrun; - ASC_ISR_CALLBACK asc_isr_callback; - - iop_base = asc_dvc->iop_base; - asc_isr_callback = asc_dvc->isr_callback; - n_q_used = 1; - scsiq = (ASC_QDONE_INFO *) & scsiq_buf; - done_q_tail = (uchar) AscGetVarDoneQTail(iop_base); - q_addr = ASC_QNO_TO_QADDR(done_q_tail); - next_qp = AscReadLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD)); - if (next_qp != ASC_QLINK_END) { - AscPutVarDoneQTail(iop_base, next_qp); - q_addr = ASC_QNO_TO_QADDR(next_qp); - sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, - asc_dvc->max_dma_count); - AscWriteLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), - (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED))); - tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix); - target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix); - if ((scsiq->cntl & QC_SG_HEAD) != 0) { - sg_q_addr = q_addr; - sg_list_qp = next_qp; - for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) { - sg_list_qp = AscReadLramByte(iop_base, - (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD)); - sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp); - if (sg_list_qp == ASC_QLINK_END) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS); - scsiq->d3.done_stat = QD_WITH_ERROR; - scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED; - goto FATAL_ERR_QDONE; - } - AscWriteLramByte(iop_base, - (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS), - QS_FREE); - } - n_q_used = sg_queue_cnt + 1; - AscPutVarDoneQTail(iop_base, sg_list_qp); - } - if (asc_dvc->queue_full_or_busy & target_id) { - cur_target_qng = AscReadLramByte(iop_base, - (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix)); - if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) { - scsi_busy = AscReadLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B); - scsi_busy &= ~target_id; - AscWriteLramByte(iop_base, - (ushort) ASCV_SCSIBUSY_B, scsi_busy); - asc_dvc->queue_full_or_busy &= ~target_id; - } - } - if (asc_dvc->cur_total_qng >= n_q_used) { - asc_dvc->cur_total_qng -= n_q_used; - if (asc_dvc->cur_dvc_qng[tid_no] != 0) { - asc_dvc->cur_dvc_qng[tid_no]--; - } - } else { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG); - scsiq->d3.done_stat = QD_WITH_ERROR; - goto FATAL_ERR_QDONE; - } - if ((scsiq->d2.srb_ptr == 0UL) || - ((scsiq->q_status & QS_ABORTED) != 0)) { - return (0x11); - } else if (scsiq->q_status == QS_DONE) { - false_overrun = FALSE; - if (scsiq->extra_bytes != 0) { - scsiq->remain_bytes += (ADV_DCNT) scsiq->extra_bytes; - } - if (scsiq->d3.done_stat == QD_WITH_ERROR) { - if (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN) { - if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) { - scsiq->d3.done_stat = QD_NO_ERROR; - scsiq->d3.host_stat = QHSTA_NO_ERROR; - } else if (false_overrun) { - scsiq->d3.done_stat = QD_NO_ERROR; - scsiq->d3.host_stat = QHSTA_NO_ERROR; - } - } else if (scsiq->d3.host_stat == - QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) { - AscStopChip(iop_base); - AscSetChipControl(iop_base, - (uchar) (CC_SCSI_RESET | CC_HALT)); - DvcDelayNanoSecond(asc_dvc, 60000); - AscSetChipControl(iop_base, CC_HALT); - AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); - AscSetChipStatus(iop_base, 0); - AscSetChipControl(iop_base, 0); - } - } - if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { - (*asc_isr_callback) (asc_dvc, scsiq); - } else { - if ((AscReadLramByte(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) == - START_STOP)) { - asc_dvc->unit_not_ready &= ~target_id; - if (scsiq->d3.done_stat != QD_NO_ERROR) { - asc_dvc->start_motor &= ~target_id; - } - } - } - return (1); - } else { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); - FATAL_ERR_QDONE: - if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { - (*asc_isr_callback) (asc_dvc, scsiq); - } - return (0x80); - } - } - return (0); + uchar next_qp; + uchar n_q_used; + uchar sg_list_qp; + uchar sg_queue_cnt; + uchar q_cnt; + uchar done_q_tail; + uchar tid_no; + ASC_SCSI_BIT_ID_TYPE scsi_busy; + ASC_SCSI_BIT_ID_TYPE target_id; + PortAddr iop_base; + ushort q_addr; + ushort sg_q_addr; + uchar cur_target_qng; + ASC_QDONE_INFO scsiq_buf; + ASC_QDONE_INFO *scsiq; + int false_overrun; + ASC_ISR_CALLBACK asc_isr_callback; + + iop_base = asc_dvc->iop_base; + asc_isr_callback = asc_dvc->isr_callback; + n_q_used = 1; + scsiq = (ASC_QDONE_INFO *)&scsiq_buf; + done_q_tail = (uchar)AscGetVarDoneQTail(iop_base); + q_addr = ASC_QNO_TO_QADDR(done_q_tail); + next_qp = AscReadLramByte(iop_base, + (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD)); + if (next_qp != ASC_QLINK_END) { + AscPutVarDoneQTail(iop_base, next_qp); + q_addr = ASC_QNO_TO_QADDR(next_qp); + sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, + asc_dvc->max_dma_count); + AscWriteLramByte(iop_base, + (ushort)(q_addr + + (ushort)ASC_SCSIQ_B_STATUS), + (uchar)(scsiq-> + q_status & (uchar)~(QS_READY | + QS_ABORTED))); + tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix); + target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix); + if ((scsiq->cntl & QC_SG_HEAD) != 0) { + sg_q_addr = q_addr; + sg_list_qp = next_qp; + for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) { + sg_list_qp = AscReadLramByte(iop_base, + (ushort)(sg_q_addr + + (ushort) + ASC_SCSIQ_B_FWD)); + sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp); + if (sg_list_qp == ASC_QLINK_END) { + AscSetLibErrorCode(asc_dvc, + ASCQ_ERR_SG_Q_LINKS); + scsiq->d3.done_stat = QD_WITH_ERROR; + scsiq->d3.host_stat = + QHSTA_D_QDONE_SG_LIST_CORRUPTED; + goto FATAL_ERR_QDONE; + } + AscWriteLramByte(iop_base, + (ushort)(sg_q_addr + (ushort) + ASC_SCSIQ_B_STATUS), + QS_FREE); + } + n_q_used = sg_queue_cnt + 1; + AscPutVarDoneQTail(iop_base, sg_list_qp); + } + if (asc_dvc->queue_full_or_busy & target_id) { + cur_target_qng = AscReadLramByte(iop_base, + (ushort)((ushort) + ASC_QADR_BEG + + (ushort) + scsiq->d2. + target_ix)); + if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) { + scsi_busy = AscReadLramByte(iop_base, (ushort) + ASCV_SCSIBUSY_B); + scsi_busy &= ~target_id; + AscWriteLramByte(iop_base, + (ushort)ASCV_SCSIBUSY_B, + scsi_busy); + asc_dvc->queue_full_or_busy &= ~target_id; + } + } + if (asc_dvc->cur_total_qng >= n_q_used) { + asc_dvc->cur_total_qng -= n_q_used; + if (asc_dvc->cur_dvc_qng[tid_no] != 0) { + asc_dvc->cur_dvc_qng[tid_no]--; + } + } else { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG); + scsiq->d3.done_stat = QD_WITH_ERROR; + goto FATAL_ERR_QDONE; + } + if ((scsiq->d2.srb_ptr == 0UL) || + ((scsiq->q_status & QS_ABORTED) != 0)) { + return (0x11); + } else if (scsiq->q_status == QS_DONE) { + false_overrun = FALSE; + if (scsiq->extra_bytes != 0) { + scsiq->remain_bytes += + (ADV_DCNT)scsiq->extra_bytes; + } + if (scsiq->d3.done_stat == QD_WITH_ERROR) { + if (scsiq->d3.host_stat == + QHSTA_M_DATA_OVER_RUN) { + if ((scsiq-> + cntl & (QC_DATA_IN | QC_DATA_OUT)) + == 0) { + scsiq->d3.done_stat = + QD_NO_ERROR; + scsiq->d3.host_stat = + QHSTA_NO_ERROR; + } else if (false_overrun) { + scsiq->d3.done_stat = + QD_NO_ERROR; + scsiq->d3.host_stat = + QHSTA_NO_ERROR; + } + } else if (scsiq->d3.host_stat == + QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) { + AscStopChip(iop_base); + AscSetChipControl(iop_base, + (uchar)(CC_SCSI_RESET + | CC_HALT)); + DvcDelayNanoSecond(asc_dvc, 60000); + AscSetChipControl(iop_base, CC_HALT); + AscSetChipStatus(iop_base, + CIW_CLR_SCSI_RESET_INT); + AscSetChipStatus(iop_base, 0); + AscSetChipControl(iop_base, 0); + } + } + if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { + (*asc_isr_callback) (asc_dvc, scsiq); + } else { + if ((AscReadLramByte(iop_base, + (ushort)(q_addr + (ushort) + ASC_SCSIQ_CDB_BEG)) + == START_STOP)) { + asc_dvc->unit_not_ready &= ~target_id; + if (scsiq->d3.done_stat != QD_NO_ERROR) { + asc_dvc->start_motor &= + ~target_id; + } + } + } + return (1); + } else { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); + FATAL_ERR_QDONE: + if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { + (*asc_isr_callback) (asc_dvc, scsiq); + } + return (0x80); + } + } + return (0); } -STATIC int -AscISR( - ASC_DVC_VAR *asc_dvc -) +static int AscISR(ASC_DVC_VAR *asc_dvc) { - ASC_CS_TYPE chipstat; - PortAddr iop_base; - ushort saved_ram_addr; - uchar ctrl_reg; - uchar saved_ctrl_reg; - int int_pending; - int status; - uchar host_flag; - - iop_base = asc_dvc->iop_base; - int_pending = FALSE; - - if (AscIsIntPending(iop_base) == 0) - { - return int_pending; - } + ASC_CS_TYPE chipstat; + PortAddr iop_base; + ushort saved_ram_addr; + uchar ctrl_reg; + uchar saved_ctrl_reg; + int int_pending; + int status; + uchar host_flag; + + iop_base = asc_dvc->iop_base; + int_pending = FALSE; + + if (AscIsIntPending(iop_base) == 0) { + return int_pending; + } - if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) - || (asc_dvc->isr_callback == 0) -) { - return (ERR); - } - if (asc_dvc->in_critical_cnt != 0) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); - return (ERR); - } - if (asc_dvc->is_in_int) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); - return (ERR); - } - asc_dvc->is_in_int = TRUE; - ctrl_reg = AscGetChipControl(iop_base); - saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET | - CC_SINGLE_STEP | CC_DIAG | CC_TEST)); - chipstat = AscGetChipStatus(iop_base); - if (chipstat & CSW_SCSI_RESET_LATCH) { - if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) { - int i = 10; - int_pending = TRUE; - asc_dvc->sdtr_done = 0; - saved_ctrl_reg &= (uchar) (~CC_HALT); - while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) && - (i-- > 0)) - { - DvcSleepMilliSecond(100); - } - AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT)); - AscSetChipControl(iop_base, CC_HALT); - AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); - AscSetChipStatus(iop_base, 0); - chipstat = AscGetChipStatus(iop_base); - } - } - saved_ram_addr = AscGetChipLramAddr(iop_base); - host_flag = AscReadLramByte(iop_base, - ASCV_HOST_FLAG_B) & (uchar) (~ASC_HOST_FLAG_IN_ISR); - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, - (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR)); - if ((chipstat & CSW_INT_PENDING) - || (int_pending) -) { - AscAckInterrupt(iop_base); - int_pending = TRUE; - if ((chipstat & CSW_HALTED) && - (ctrl_reg & CC_SINGLE_STEP)) { - if (AscIsrChipHalted(asc_dvc) == ERR) { - goto ISR_REPORT_QDONE_FATAL_ERROR; - } else { - saved_ctrl_reg &= (uchar) (~CC_HALT); - } - } else { - ISR_REPORT_QDONE_FATAL_ERROR: - if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) { - while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) { - } - } else { - do { - if ((status = AscIsrQDone(asc_dvc)) == 1) { - break; - } - } while (status == 0x11); - } - if ((status & 0x80) != 0) - int_pending = ERR; - } - } - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); - AscSetChipLramAddr(iop_base, saved_ram_addr); - AscSetChipControl(iop_base, saved_ctrl_reg); - asc_dvc->is_in_int = FALSE; - return (int_pending); + if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) + || (asc_dvc->isr_callback == 0) + ) { + return (ERR); + } + if (asc_dvc->in_critical_cnt != 0) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); + return (ERR); + } + if (asc_dvc->is_in_int) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); + return (ERR); + } + asc_dvc->is_in_int = TRUE; + ctrl_reg = AscGetChipControl(iop_base); + saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET | + CC_SINGLE_STEP | CC_DIAG | CC_TEST)); + chipstat = AscGetChipStatus(iop_base); + if (chipstat & CSW_SCSI_RESET_LATCH) { + if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) { + int i = 10; + int_pending = TRUE; + asc_dvc->sdtr_done = 0; + saved_ctrl_reg &= (uchar)(~CC_HALT); + while ((AscGetChipStatus(iop_base) & + CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) { + DvcSleepMilliSecond(100); + } + AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT)); + AscSetChipControl(iop_base, CC_HALT); + AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); + AscSetChipStatus(iop_base, 0); + chipstat = AscGetChipStatus(iop_base); + } + } + saved_ram_addr = AscGetChipLramAddr(iop_base); + host_flag = AscReadLramByte(iop_base, + ASCV_HOST_FLAG_B) & + (uchar)(~ASC_HOST_FLAG_IN_ISR); + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, + (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR)); + if ((chipstat & CSW_INT_PENDING) + || (int_pending) + ) { + AscAckInterrupt(iop_base); + int_pending = TRUE; + if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) { + if (AscIsrChipHalted(asc_dvc) == ERR) { + goto ISR_REPORT_QDONE_FATAL_ERROR; + } else { + saved_ctrl_reg &= (uchar)(~CC_HALT); + } + } else { + ISR_REPORT_QDONE_FATAL_ERROR: + if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) { + while (((status = + AscIsrQDone(asc_dvc)) & 0x01) != 0) { + } + } else { + do { + if ((status = + AscIsrQDone(asc_dvc)) == 1) { + break; + } + } while (status == 0x11); + } + if ((status & 0x80) != 0) + int_pending = ERR; + } + } + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); + AscSetChipLramAddr(iop_base, saved_ram_addr); + AscSetChipControl(iop_base, saved_ctrl_reg); + asc_dvc->is_in_int = FALSE; + return (int_pending); } /* Microcode buffer is kept after initialization for error recovery. */ -STATIC uchar _asc_mcode_buf[] = -{ - 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40, - 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, 0xC2, 0x00, 0x92, 0x80, - 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, - 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62, - 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, - 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, - 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88, - 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00, 0x84, 0x97, 0x07, 0xA6, - 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, - 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6, - 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, 0x34, 0x01, 0x00, 0x33, - 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, - 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23, - 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01, 0x00, 0x33, 0x0A, 0x00, - 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01, 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, - 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01, - 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3, 0x3C, 0x01, 0x00, 0x05, - 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, - 0xBE, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, - 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, 0xC2, 0x88, 0x06, 0x23, - 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, - 0xDA, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, - 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x84, 0x97, - 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, - 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, - 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88, 0x04, 0x98, 0xF0, 0x80, - 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02, 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, - 0x4C, 0x04, 0x46, 0x82, 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95, - 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02, 0x07, 0xA6, 0x5A, 0x02, - 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02, 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, - 0x48, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC, - 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, - 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, - 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02, - 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E, 0x80, 0x63, 0x00, 0x43, - 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, - 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82, - 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8, 0x00, 0x33, 0x1F, 0x00, - 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, - 0x14, 0x03, 0x00, 0xA6, 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6, - 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xEE, 0x82, - 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, - 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98, - 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6, 0x3C, 0x04, 0x06, 0xA6, - 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, - 0x60, 0x96, 0x32, 0x83, 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33, - 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05, 0xFF, 0xA2, 0x7A, 0x03, - 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83, 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, - 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03, - 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6, 0xA4, 0x03, 0x00, 0xA6, - 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, - 0xD4, 0x83, 0x7C, 0x95, 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42, - 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95, 0xC0, 0x83, 0x00, 0x33, - 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, - 0xA1, 0x01, 0x10, 0x84, 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, - 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04, 0x06, 0xA6, 0x0A, 0x04, - 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, - 0x07, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, - 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, 0x38, 0x04, 0x00, 0x33, - 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, - 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63, - 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, - 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, - 0x00, 0x33, 0x1D, 0x00, 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, - 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, 0x08, 0x23, 0x22, 0xA3, - 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, - 0xF8, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98, - 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xE8, 0x81, - 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, - 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23, - 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xF4, 0x04, 0x00, 0x33, - 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, - 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05, - 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, 0x46, 0x97, 0xCD, 0x04, - 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, - 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6, - 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, - 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, - 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, - 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xF8, 0x05, - 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, - 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05, - 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x62, 0x97, 0x04, 0x85, - 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, - 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0, - 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, 0x80, 0x67, 0x80, 0x63, - 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, - 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00, - 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, 0x07, 0x41, 0x83, 0x03, - 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, - 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05, - 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, - 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, - 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, - 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, 0xDF, 0x00, 0x06, 0xA6, - 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, - 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06, - 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63, - 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, - 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E, - 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x07, 0xA6, 0xD6, 0x06, - 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, - 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E, - 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, - 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, - 0x2C, 0x00, 0xC2, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, - 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88, 0x00, 0x00, 0x80, 0x67, - 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, - 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00, - 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, 0x81, 0x05, - 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, - 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01, - 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, 0x70, 0x00, - 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, - 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01, - 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xC4, 0x07, 0x00, 0x33, - 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, - 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07, - 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, 0x00, 0x63, - 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, - 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0, - 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF3, 0x04, - 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, - 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98, - 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x5A, 0x88, 0x02, 0x01, - 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, - 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08, - 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x38, 0x2B, - 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, - 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36, - 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, - 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, - 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, - 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, - 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, - 0xF1, 0xC7, 0x41, 0x23, 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84, +static uchar _asc_mcode_buf[] = { + 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05, 0x01, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x88, + 0x00, 0x00, 0x00, 0x00, + 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, + 0x03, 0x23, 0x36, 0x40, + 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, + 0xC2, 0x00, 0x92, 0x80, + 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, + 0xB6, 0x00, 0x92, 0x80, + 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, + 0x92, 0x80, 0x80, 0x62, + 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, + 0xCD, 0x04, 0x4D, 0x00, + 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, + 0xE6, 0x84, 0xD2, 0xC1, + 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, + 0xC6, 0x81, 0xC2, 0x88, + 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00, + 0x84, 0x97, 0x07, 0xA6, + 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x01, 0xDE, + 0xC2, 0x88, 0xCE, 0x00, + 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, + 0x80, 0x63, 0x07, 0xA6, + 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, + 0x34, 0x01, 0x00, 0x33, + 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, + 0x68, 0x98, 0x4D, 0x04, + 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, + 0xF8, 0x88, 0xFB, 0x23, + 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01, + 0x00, 0x33, 0x0A, 0x00, + 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01, 0x00, 0x33, 0x0B, 0x00, + 0xC2, 0x88, 0xCD, 0x04, + 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, + 0x06, 0xAB, 0x82, 0x01, + 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3, + 0x3C, 0x01, 0x00, 0x05, + 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, + 0x15, 0x23, 0xA1, 0x01, + 0xBE, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, + 0x06, 0x61, 0x00, 0xA0, + 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, + 0xC2, 0x88, 0x06, 0x23, + 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xD4, 0x01, + 0x57, 0x60, 0x00, 0xA0, + 0xDA, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, + 0x4B, 0x00, 0x06, 0x61, + 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC, + 0x4F, 0x00, 0x84, 0x97, + 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x62, 0x97, + 0x48, 0x04, 0x84, 0x80, + 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, + 0x81, 0x73, 0x06, 0x29, + 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88, + 0x04, 0x98, 0xF0, 0x80, + 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02, 0x7C, 0x95, 0x06, 0xA6, + 0x34, 0x02, 0x03, 0xA6, + 0x4C, 0x04, 0x46, 0x82, 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, + 0x46, 0x82, 0xFE, 0x95, + 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02, + 0x07, 0xA6, 0x5A, 0x02, + 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02, 0xC2, 0x88, 0x7C, 0x95, + 0x48, 0x82, 0x60, 0x96, + 0x48, 0x82, 0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, + 0x04, 0x01, 0x0C, 0xDC, + 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, + 0x6F, 0x00, 0xA5, 0x01, + 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, + 0x02, 0xA6, 0xAA, 0x02, + 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, + 0x01, 0xA6, 0xB4, 0x02, + 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E, + 0x80, 0x63, 0x00, 0x43, + 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, + 0x04, 0x61, 0x84, 0x01, + 0x10, 0x31, 0x12, 0x35, 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, + 0x00, 0x00, 0xEA, 0x82, + 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8, + 0x00, 0x33, 0x1F, 0x00, + 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, + 0xB6, 0x2D, 0x01, 0xA6, + 0x14, 0x03, 0x00, 0xA6, 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, + 0x10, 0x03, 0x03, 0xA6, + 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88, + 0x7C, 0x95, 0xEE, 0x82, + 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x64, 0xE4, + 0x04, 0x01, 0x2D, 0xC8, + 0x31, 0x05, 0x07, 0x01, 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, + 0x05, 0x05, 0x86, 0x98, + 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6, + 0x3C, 0x04, 0x06, 0xA6, + 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC2, 0x88, + 0x7C, 0x95, 0x32, 0x83, + 0x60, 0x96, 0x32, 0x83, 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, + 0xEB, 0x04, 0x00, 0x33, + 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05, + 0xFF, 0xA2, 0x7A, 0x03, + 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83, 0x05, 0x05, 0x15, 0x01, + 0x00, 0xA2, 0x9A, 0x03, + 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, + 0x01, 0xA6, 0x96, 0x03, + 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6, + 0xA4, 0x03, 0x00, 0xA6, + 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA4, 0x03, + 0x07, 0xA6, 0xB2, 0x03, + 0xD4, 0x83, 0x7C, 0x95, 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, + 0xA8, 0x98, 0x80, 0x42, + 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95, + 0xC0, 0x83, 0x00, 0x33, + 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23, + 0xA0, 0x01, 0x12, 0x23, + 0xA1, 0x01, 0x10, 0x84, 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, + 0x80, 0x67, 0x05, 0x23, + 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04, + 0x06, 0xA6, 0x0A, 0x04, + 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0xF4, 0x83, 0x60, 0x96, + 0xF4, 0x83, 0x20, 0x84, + 0x07, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, + 0x83, 0x03, 0x80, 0x63, + 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, + 0x38, 0x04, 0x00, 0x33, + 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, + 0x1D, 0x01, 0x06, 0xCC, + 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, + 0xA2, 0x0D, 0x80, 0x63, + 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03, + 0x80, 0x63, 0xA3, 0x01, + 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, + 0x76, 0x04, 0xE0, 0x00, + 0x00, 0x33, 0x1D, 0x00, 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, + 0x00, 0x33, 0x1E, 0x00, + 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, + 0x08, 0x23, 0x22, 0xA3, + 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, + 0xC4, 0x04, 0x42, 0x23, + 0xF8, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, + 0xF8, 0x88, 0x04, 0x98, + 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, + 0x81, 0x62, 0xE8, 0x81, + 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB4, 0x98, + 0x00, 0x33, 0x00, 0x81, + 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, + 0xF8, 0x88, 0x04, 0x23, + 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, + 0xF4, 0x04, 0x00, 0x33, + 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, + 0x04, 0x23, 0xA0, 0x01, + 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, + 0x00, 0xA3, 0x22, 0x05, + 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, + 0x46, 0x97, 0xCD, 0x04, + 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, + 0x82, 0x01, 0x34, 0x85, + 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, + 0x1D, 0x01, 0x04, 0xD6, + 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, + 0x49, 0x00, 0x81, 0x01, + 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, + 0x49, 0x04, 0x80, 0x01, + 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, + 0x01, 0x23, 0xEA, 0x00, + 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, + 0x07, 0xA4, 0xF8, 0x05, + 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, + 0xC2, 0x88, 0x04, 0xA0, + 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, + 0x00, 0xA2, 0xA4, 0x05, + 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, + 0x62, 0x97, 0x04, 0x85, + 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, + 0xF4, 0x85, 0x03, 0xA0, + 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, + 0xCC, 0x86, 0x07, 0xA0, + 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, + 0x80, 0x67, 0x80, 0x63, + 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, + 0xF8, 0x88, 0x07, 0x23, + 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, + 0x00, 0x63, 0x4A, 0x00, + 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, + 0x07, 0x41, 0x83, 0x03, + 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC2, 0x88, + 0x1D, 0x01, 0x01, 0xD6, + 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, + 0x07, 0xA6, 0x7C, 0x05, + 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, + 0x52, 0x00, 0x06, 0x61, + 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, + 0x00, 0x63, 0x1D, 0x01, + 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, + 0x07, 0x41, 0x00, 0x63, + 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, + 0xDF, 0x00, 0x06, 0xA6, + 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, + 0x00, 0x40, 0xC0, 0x20, + 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, + 0x06, 0xA6, 0x94, 0x06, + 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, + 0x40, 0x0E, 0x80, 0x63, + 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, + 0x80, 0x63, 0x00, 0x43, + 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, + 0x80, 0x67, 0x40, 0x0E, + 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, + 0x07, 0xA6, 0xD6, 0x06, + 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, + 0x0A, 0x2B, 0x07, 0xA6, + 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, + 0xF4, 0x06, 0xC0, 0x0E, + 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, + 0x81, 0x62, 0x04, 0x01, + 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, + 0x8C, 0x06, 0x00, 0x33, + 0x2C, 0x00, 0xC2, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, + 0x80, 0x63, 0x06, 0xA6, + 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88, + 0x00, 0x00, 0x80, 0x67, + 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, + 0xBF, 0x23, 0x04, 0x61, + 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, + 0x00, 0x01, 0xF2, 0x00, + 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, + 0x80, 0x05, 0x81, 0x05, + 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, + 0x70, 0x00, 0x81, 0x01, + 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, + 0x70, 0x00, 0x80, 0x01, + 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, + 0xF1, 0x00, 0x70, 0x00, + 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, + 0x71, 0x04, 0x70, 0x00, + 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, + 0xA3, 0x01, 0xA2, 0x01, + 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, + 0xC4, 0x07, 0x00, 0x33, + 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, + 0x48, 0x00, 0xB0, 0x01, + 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, + 0x00, 0xA2, 0xE4, 0x07, + 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, + 0x05, 0x05, 0x00, 0x63, + 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, + 0x76, 0x08, 0x80, 0x02, + 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, + 0x00, 0x02, 0x00, 0xA0, + 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, + 0x00, 0x63, 0xF3, 0x04, + 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, + 0x00, 0xA2, 0x44, 0x08, + 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, + 0x24, 0x08, 0x04, 0x98, + 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, + 0x5A, 0x88, 0x02, 0x01, + 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, + 0x00, 0xA3, 0x64, 0x08, + 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, + 0x06, 0xA6, 0x76, 0x08, + 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, + 0x00, 0x63, 0x38, 0x2B, + 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, + 0x05, 0x05, 0xB2, 0x09, + 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, + 0x80, 0x32, 0x80, 0x36, + 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, + 0x40, 0x36, 0x40, 0x3A, + 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB4, 0x08, + 0x5D, 0x00, 0xFE, 0xC3, + 0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, + 0xFF, 0xFD, 0x80, 0x73, + 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, + 0xA1, 0x23, 0xA1, 0x01, + 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, + 0x80, 0x00, 0x03, 0xC2, + 0xF1, 0xC7, 0x41, 0x23, 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, + 0xA0, 0x01, 0xE6, 0x84, }; -STATIC ushort _asc_mcode_size = sizeof(_asc_mcode_buf); -STATIC ADV_DCNT _asc_mcode_chksum = 0x012C453FUL; +static ushort _asc_mcode_size = sizeof(_asc_mcode_buf); +static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL; #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16 -STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = -{ - INQUIRY, - REQUEST_SENSE, - READ_CAPACITY, - READ_TOC, - MODE_SELECT, - MODE_SENSE, - MODE_SELECT_10, - MODE_SENSE_10, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF +static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = { + INQUIRY, + REQUEST_SENSE, + READ_CAPACITY, + READ_TOC, + MODE_SELECT, + MODE_SENSE, + MODE_SELECT_10, + MODE_SENSE_10, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF }; -STATIC int -AscExeScsiQueue( - ASC_DVC_VAR *asc_dvc, - ASC_SCSI_Q *scsiq -) +static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq) { - PortAddr iop_base; - ulong last_int_level; - int sta; - int n_q_required; - int disable_syn_offset_one_fix; - int i; - ASC_PADDR addr; - ASC_EXE_CALLBACK asc_exe_callback; - ushort sg_entry_cnt = 0; - ushort sg_entry_cnt_minus_one = 0; - uchar target_ix; - uchar tid_no; - uchar sdtr_data; - uchar extra_bytes; - uchar scsi_cmd; - uchar disable_cmd; - ASC_SG_HEAD *sg_head; - ASC_DCNT data_cnt; - - iop_base = asc_dvc->iop_base; - sg_head = scsiq->sg_head; - asc_exe_callback = asc_dvc->exe_callback; - if (asc_dvc->err_code != 0) - return (ERR); - if (scsiq == (ASC_SCSI_Q *) 0L) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR); - return (ERR); - } - scsiq->q1.q_no = 0; - if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) { - scsiq->q1.extra_bytes = 0; - } - sta = 0; - target_ix = scsiq->q2.target_ix; - tid_no = ASC_TIX_TO_TID(target_ix); - n_q_required = 1; - if (scsiq->cdbptr[0] == REQUEST_SENSE) { - if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { - asc_dvc->sdtr_done &= ~scsiq->q1.target_id; - sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); - AscMsgOutSDTR(asc_dvc, - asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) & - (uchar) (asc_dvc->max_sdtr_index - 1)], - (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); - scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); - } - } - last_int_level = DvcEnterCritical(); - if (asc_dvc->in_critical_cnt != 0) { - DvcLeaveCritical(last_int_level); - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); - return (ERR); - } - asc_dvc->in_critical_cnt++; - if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { - if ((sg_entry_cnt = sg_head->entry_cnt) == 0) { - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return (ERR); - } + PortAddr iop_base; + ulong last_int_level; + int sta; + int n_q_required; + int disable_syn_offset_one_fix; + int i; + ASC_PADDR addr; + ASC_EXE_CALLBACK asc_exe_callback; + ushort sg_entry_cnt = 0; + ushort sg_entry_cnt_minus_one = 0; + uchar target_ix; + uchar tid_no; + uchar sdtr_data; + uchar extra_bytes; + uchar scsi_cmd; + uchar disable_cmd; + ASC_SG_HEAD *sg_head; + ASC_DCNT data_cnt; + + iop_base = asc_dvc->iop_base; + sg_head = scsiq->sg_head; + asc_exe_callback = asc_dvc->exe_callback; + if (asc_dvc->err_code != 0) + return (ERR); + if (scsiq == (ASC_SCSI_Q *)0L) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR); + return (ERR); + } + scsiq->q1.q_no = 0; + if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) { + scsiq->q1.extra_bytes = 0; + } + sta = 0; + target_ix = scsiq->q2.target_ix; + tid_no = ASC_TIX_TO_TID(target_ix); + n_q_required = 1; + if (scsiq->cdbptr[0] == REQUEST_SENSE) { + if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { + asc_dvc->sdtr_done &= ~scsiq->q1.target_id; + sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); + AscMsgOutSDTR(asc_dvc, + asc_dvc-> + sdtr_period_tbl[(sdtr_data >> 4) & + (uchar)(asc_dvc-> + max_sdtr_index - + 1)], + (uchar)(sdtr_data & (uchar) + ASC_SYN_MAX_OFFSET)); + scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); + } + } + last_int_level = DvcEnterCritical(); + if (asc_dvc->in_critical_cnt != 0) { + DvcLeaveCritical(last_int_level); + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); + return (ERR); + } + asc_dvc->in_critical_cnt++; + if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { + if ((sg_entry_cnt = sg_head->entry_cnt) == 0) { + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + return (ERR); + } #if !CC_VERY_LONG_SG_LIST - if (sg_entry_cnt > ASC_MAX_SG_LIST) - { - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return(ERR); - } + if (sg_entry_cnt > ASC_MAX_SG_LIST) { + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + return (ERR); + } #endif /* !CC_VERY_LONG_SG_LIST */ - if (sg_entry_cnt == 1) { - scsiq->q1.data_addr = (ADV_PADDR) sg_head->sg_list[0].addr; - scsiq->q1.data_cnt = (ADV_DCNT) sg_head->sg_list[0].bytes; - scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); - } - sg_entry_cnt_minus_one = sg_entry_cnt - 1; - } - scsi_cmd = scsiq->cdbptr[0]; - disable_syn_offset_one_fix = FALSE; - if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) && - !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) { - if (scsiq->q1.cntl & QC_SG_HEAD) { - data_cnt = 0; - for (i = 0; i < sg_entry_cnt; i++) { - data_cnt += (ADV_DCNT) le32_to_cpu(sg_head->sg_list[i].bytes); - } - } else { - data_cnt = le32_to_cpu(scsiq->q1.data_cnt); - } - if (data_cnt != 0UL) { - if (data_cnt < 512UL) { - disable_syn_offset_one_fix = TRUE; - } else { - for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; i++) { - disable_cmd = _syn_offset_one_disable_cmd[i]; - if (disable_cmd == 0xFF) { - break; - } - if (scsi_cmd == disable_cmd) { - disable_syn_offset_one_fix = TRUE; - break; - } - } - } - } - } - if (disable_syn_offset_one_fix) { - scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; - scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | - ASC_TAG_FLAG_DISABLE_DISCONNECT); - } else { - scsiq->q2.tag_code &= 0x27; - } - if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { - if (asc_dvc->bug_fix_cntl) { - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { - if ((scsi_cmd == READ_6) || - (scsi_cmd == READ_10)) { - addr = - (ADV_PADDR) le32_to_cpu( - sg_head->sg_list[sg_entry_cnt_minus_one].addr) + - (ADV_DCNT) le32_to_cpu( - sg_head->sg_list[sg_entry_cnt_minus_one].bytes); - extra_bytes = (uchar) ((ushort) addr & 0x0003); - if ((extra_bytes != 0) && - ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) - == 0)) { - scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES; - scsiq->q1.extra_bytes = extra_bytes; - data_cnt = le32_to_cpu( - sg_head->sg_list[sg_entry_cnt_minus_one].bytes); - data_cnt -= (ASC_DCNT) extra_bytes; - sg_head->sg_list[sg_entry_cnt_minus_one].bytes = - cpu_to_le32(data_cnt); - } - } - } - } - sg_head->entry_to_copy = sg_head->entry_cnt; + if (sg_entry_cnt == 1) { + scsiq->q1.data_addr = + (ADV_PADDR)sg_head->sg_list[0].addr; + scsiq->q1.data_cnt = + (ADV_DCNT)sg_head->sg_list[0].bytes; + scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); + } + sg_entry_cnt_minus_one = sg_entry_cnt - 1; + } + scsi_cmd = scsiq->cdbptr[0]; + disable_syn_offset_one_fix = FALSE; + if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) && + !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) { + if (scsiq->q1.cntl & QC_SG_HEAD) { + data_cnt = 0; + for (i = 0; i < sg_entry_cnt; i++) { + data_cnt += + (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i]. + bytes); + } + } else { + data_cnt = le32_to_cpu(scsiq->q1.data_cnt); + } + if (data_cnt != 0UL) { + if (data_cnt < 512UL) { + disable_syn_offset_one_fix = TRUE; + } else { + for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; + i++) { + disable_cmd = + _syn_offset_one_disable_cmd[i]; + if (disable_cmd == 0xFF) { + break; + } + if (scsi_cmd == disable_cmd) { + disable_syn_offset_one_fix = + TRUE; + break; + } + } + } + } + } + if (disable_syn_offset_one_fix) { + scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; + scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | + ASC_TAG_FLAG_DISABLE_DISCONNECT); + } else { + scsiq->q2.tag_code &= 0x27; + } + if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { + if (asc_dvc->bug_fix_cntl) { + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { + if ((scsi_cmd == READ_6) || + (scsi_cmd == READ_10)) { + addr = + (ADV_PADDR)le32_to_cpu(sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + addr) + + (ADV_DCNT)le32_to_cpu(sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + bytes); + extra_bytes = + (uchar)((ushort)addr & 0x0003); + if ((extra_bytes != 0) + && + ((scsiq->q2. + tag_code & + ASC_TAG_FLAG_EXTRA_BYTES) + == 0)) { + scsiq->q2.tag_code |= + ASC_TAG_FLAG_EXTRA_BYTES; + scsiq->q1.extra_bytes = + extra_bytes; + data_cnt = + le32_to_cpu(sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + bytes); + data_cnt -= + (ASC_DCNT) extra_bytes; + sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + bytes = + cpu_to_le32(data_cnt); + } + } + } + } + sg_head->entry_to_copy = sg_head->entry_cnt; #if CC_VERY_LONG_SG_LIST - /* - * Set the sg_entry_cnt to the maximum possible. The rest of - * the SG elements will be copied when the RISC completes the - * SG elements that fit and halts. - */ - if (sg_entry_cnt > ASC_MAX_SG_LIST) - { - sg_entry_cnt = ASC_MAX_SG_LIST; - } + /* + * Set the sg_entry_cnt to the maximum possible. The rest of + * the SG elements will be copied when the RISC completes the + * SG elements that fit and halts. + */ + if (sg_entry_cnt > ASC_MAX_SG_LIST) { + sg_entry_cnt = ASC_MAX_SG_LIST; + } #endif /* CC_VERY_LONG_SG_LIST */ - n_q_required = AscSgListToQueue(sg_entry_cnt); - if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >= - (uint) n_q_required) || ((scsiq->q1.cntl & QC_URGENT) != 0)) { - if ((sta = AscSendScsiQueue(asc_dvc, scsiq, - n_q_required)) == 1) { - asc_dvc->in_critical_cnt--; - if (asc_exe_callback != 0) { - (*asc_exe_callback) (asc_dvc, scsiq); - } - DvcLeaveCritical(last_int_level); - return (sta); - } - } - } else { - if (asc_dvc->bug_fix_cntl) { - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { - if ((scsi_cmd == READ_6) || - (scsi_cmd == READ_10)) { - addr = le32_to_cpu(scsiq->q1.data_addr) + - le32_to_cpu(scsiq->q1.data_cnt); - extra_bytes = (uchar) ((ushort) addr & 0x0003); - if ((extra_bytes != 0) && - ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) - == 0)) { - data_cnt = le32_to_cpu(scsiq->q1.data_cnt); - if (((ushort) data_cnt & 0x01FF) == 0) { - scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES; - data_cnt -= (ASC_DCNT) extra_bytes; - scsiq->q1.data_cnt = cpu_to_le32(data_cnt); - scsiq->q1.extra_bytes = extra_bytes; - } - } - } - } - } - n_q_required = 1; - if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || - ((scsiq->q1.cntl & QC_URGENT) != 0)) { - if ((sta = AscSendScsiQueue(asc_dvc, scsiq, - n_q_required)) == 1) { - asc_dvc->in_critical_cnt--; - if (asc_exe_callback != 0) { - (*asc_exe_callback) (asc_dvc, scsiq); - } - DvcLeaveCritical(last_int_level); - return (sta); - } - } - } - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return (sta); + n_q_required = AscSgListToQueue(sg_entry_cnt); + if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >= + (uint) n_q_required) + || ((scsiq->q1.cntl & QC_URGENT) != 0)) { + if ((sta = + AscSendScsiQueue(asc_dvc, scsiq, + n_q_required)) == 1) { + asc_dvc->in_critical_cnt--; + if (asc_exe_callback != 0) { + (*asc_exe_callback) (asc_dvc, scsiq); + } + DvcLeaveCritical(last_int_level); + return (sta); + } + } + } else { + if (asc_dvc->bug_fix_cntl) { + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { + if ((scsi_cmd == READ_6) || + (scsi_cmd == READ_10)) { + addr = + le32_to_cpu(scsiq->q1.data_addr) + + le32_to_cpu(scsiq->q1.data_cnt); + extra_bytes = + (uchar)((ushort)addr & 0x0003); + if ((extra_bytes != 0) + && + ((scsiq->q2. + tag_code & + ASC_TAG_FLAG_EXTRA_BYTES) + == 0)) { + data_cnt = + le32_to_cpu(scsiq->q1. + data_cnt); + if (((ushort)data_cnt & 0x01FF) + == 0) { + scsiq->q2.tag_code |= + ASC_TAG_FLAG_EXTRA_BYTES; + data_cnt -= (ASC_DCNT) + extra_bytes; + scsiq->q1.data_cnt = + cpu_to_le32 + (data_cnt); + scsiq->q1.extra_bytes = + extra_bytes; + } + } + } + } + } + n_q_required = 1; + if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || + ((scsiq->q1.cntl & QC_URGENT) != 0)) { + if ((sta = AscSendScsiQueue(asc_dvc, scsiq, + n_q_required)) == 1) { + asc_dvc->in_critical_cnt--; + if (asc_exe_callback != 0) { + (*asc_exe_callback) (asc_dvc, scsiq); + } + DvcLeaveCritical(last_int_level); + return (sta); + } + } + } + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + return (sta); } -STATIC int -AscSendScsiQueue( - ASC_DVC_VAR *asc_dvc, - ASC_SCSI_Q *scsiq, - uchar n_q_required -) +static int +AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required) { - PortAddr iop_base; - uchar free_q_head; - uchar next_qp; - uchar tid_no; - uchar target_ix; - int sta; - - iop_base = asc_dvc->iop_base; - target_ix = scsiq->q2.target_ix; - tid_no = ASC_TIX_TO_TID(target_ix); - sta = 0; - free_q_head = (uchar) AscGetVarFreeQHead(iop_base); - if (n_q_required > 1) { - if ((next_qp = AscAllocMultipleFreeQueue(iop_base, - free_q_head, (uchar) (n_q_required))) - != (uchar) ASC_QLINK_END) { - asc_dvc->last_q_shortage = 0; - scsiq->sg_head->queue_cnt = n_q_required - 1; - scsiq->q1.q_no = free_q_head; - if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq, - free_q_head)) == 1) { - AscPutVarFreeQHead(iop_base, next_qp); - asc_dvc->cur_total_qng += (uchar) (n_q_required); - asc_dvc->cur_dvc_qng[tid_no]++; - } - return (sta); - } - } else if (n_q_required == 1) { - if ((next_qp = AscAllocFreeQueue(iop_base, - free_q_head)) != ASC_QLINK_END) { - scsiq->q1.q_no = free_q_head; - if ((sta = AscPutReadyQueue(asc_dvc, scsiq, - free_q_head)) == 1) { - AscPutVarFreeQHead(iop_base, next_qp); - asc_dvc->cur_total_qng++; - asc_dvc->cur_dvc_qng[tid_no]++; - } - return (sta); - } - } - return (sta); + PortAddr iop_base; + uchar free_q_head; + uchar next_qp; + uchar tid_no; + uchar target_ix; + int sta; + + iop_base = asc_dvc->iop_base; + target_ix = scsiq->q2.target_ix; + tid_no = ASC_TIX_TO_TID(target_ix); + sta = 0; + free_q_head = (uchar)AscGetVarFreeQHead(iop_base); + if (n_q_required > 1) { + if ((next_qp = AscAllocMultipleFreeQueue(iop_base, + free_q_head, (uchar) + (n_q_required))) + != (uchar)ASC_QLINK_END) { + asc_dvc->last_q_shortage = 0; + scsiq->sg_head->queue_cnt = n_q_required - 1; + scsiq->q1.q_no = free_q_head; + if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq, + free_q_head)) == 1) { + AscPutVarFreeQHead(iop_base, next_qp); + asc_dvc->cur_total_qng += (uchar)(n_q_required); + asc_dvc->cur_dvc_qng[tid_no]++; + } + return (sta); + } + } else if (n_q_required == 1) { + if ((next_qp = AscAllocFreeQueue(iop_base, + free_q_head)) != + ASC_QLINK_END) { + scsiq->q1.q_no = free_q_head; + if ((sta = AscPutReadyQueue(asc_dvc, scsiq, + free_q_head)) == 1) { + AscPutVarFreeQHead(iop_base, next_qp); + asc_dvc->cur_total_qng++; + asc_dvc->cur_dvc_qng[tid_no]++; + } + return (sta); + } + } + return (sta); } -STATIC int -AscSgListToQueue( - int sg_list -) +static int AscSgListToQueue(int sg_list) { - int n_sg_list_qs; + int n_sg_list_qs; - n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); - if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) - n_sg_list_qs++; - return (n_sg_list_qs + 1); + n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); + if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) + n_sg_list_qs++; + return (n_sg_list_qs + 1); } - -STATIC uint -AscGetNumOfFreeQueue( - ASC_DVC_VAR *asc_dvc, - uchar target_ix, - uchar n_qs -) +static uint +AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs) { - uint cur_used_qs; - uint cur_free_qs; - ASC_SCSI_BIT_ID_TYPE target_id; - uchar tid_no; - - target_id = ASC_TIX_TO_TARGET_ID(target_ix); - tid_no = ASC_TIX_TO_TID(target_ix); - if ((asc_dvc->unit_not_ready & target_id) || - (asc_dvc->queue_full_or_busy & target_id)) { - return (0); - } - if (n_qs == 1) { - cur_used_qs = (uint) asc_dvc->cur_total_qng + - (uint) asc_dvc->last_q_shortage + - (uint) ASC_MIN_FREE_Q; - } else { - cur_used_qs = (uint) asc_dvc->cur_total_qng + - (uint) ASC_MIN_FREE_Q; - } - if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { - cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; - if (asc_dvc->cur_dvc_qng[tid_no] >= - asc_dvc->max_dvc_qng[tid_no]) { - return (0); - } - return (cur_free_qs); - } - if (n_qs > 1) { - if ((n_qs > asc_dvc->last_q_shortage) && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) { - asc_dvc->last_q_shortage = n_qs; - } - } - return (0); + uint cur_used_qs; + uint cur_free_qs; + ASC_SCSI_BIT_ID_TYPE target_id; + uchar tid_no; + + target_id = ASC_TIX_TO_TARGET_ID(target_ix); + tid_no = ASC_TIX_TO_TID(target_ix); + if ((asc_dvc->unit_not_ready & target_id) || + (asc_dvc->queue_full_or_busy & target_id)) { + return (0); + } + if (n_qs == 1) { + cur_used_qs = (uint) asc_dvc->cur_total_qng + + (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q; + } else { + cur_used_qs = (uint) asc_dvc->cur_total_qng + + (uint) ASC_MIN_FREE_Q; + } + if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { + cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; + if (asc_dvc->cur_dvc_qng[tid_no] >= + asc_dvc->max_dvc_qng[tid_no]) { + return (0); + } + return (cur_free_qs); + } + if (n_qs > 1) { + if ((n_qs > asc_dvc->last_q_shortage) + && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) { + asc_dvc->last_q_shortage = n_qs; + } + } + return (0); } -STATIC int -AscPutReadyQueue( - ASC_DVC_VAR *asc_dvc, - ASC_SCSI_Q *scsiq, - uchar q_no -) +static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) { - ushort q_addr; - uchar tid_no; - uchar sdtr_data; - uchar syn_period_ix; - uchar syn_offset; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && - ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { - tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); - sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); - syn_period_ix = (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1); - syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; - AscMsgOutSDTR(asc_dvc, - asc_dvc->sdtr_period_tbl[syn_period_ix], - syn_offset); - scsiq->q1.cntl |= QC_MSG_OUT; - } - q_addr = ASC_QNO_TO_QADDR(q_no); - if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { - scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG ; - } - scsiq->q1.status = QS_FREE; - AscMemWordCopyPtrToLram(iop_base, - q_addr + ASC_SCSIQ_CDB_BEG, - (uchar *) scsiq->cdbptr, - scsiq->q2.cdb_len >> 1); - - DvcPutScsiQ(iop_base, - q_addr + ASC_SCSIQ_CPY_BEG, - (uchar *) &scsiq->q1.cntl, - ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1); - AscWriteLramWord(iop_base, - (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), - (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY)); - return (1); + ushort q_addr; + uchar tid_no; + uchar sdtr_data; + uchar syn_period_ix; + uchar syn_offset; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && + ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { + tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); + sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); + syn_period_ix = + (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1); + syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; + AscMsgOutSDTR(asc_dvc, + asc_dvc->sdtr_period_tbl[syn_period_ix], + syn_offset); + scsiq->q1.cntl |= QC_MSG_OUT; + } + q_addr = ASC_QNO_TO_QADDR(q_no); + if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { + scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; + } + scsiq->q1.status = QS_FREE; + AscMemWordCopyPtrToLram(iop_base, + q_addr + ASC_SCSIQ_CDB_BEG, + (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1); + + DvcPutScsiQ(iop_base, + q_addr + ASC_SCSIQ_CPY_BEG, + (uchar *)&scsiq->q1.cntl, + ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1); + AscWriteLramWord(iop_base, + (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS), + (ushort)(((ushort)scsiq->q1. + q_no << 8) | (ushort)QS_READY)); + return (1); } -STATIC int -AscPutReadySgListQueue( - ASC_DVC_VAR *asc_dvc, - ASC_SCSI_Q *scsiq, - uchar q_no -) +static int +AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) { - int sta; - int i; - ASC_SG_HEAD *sg_head; - ASC_SG_LIST_Q scsi_sg_q; - ASC_DCNT saved_data_addr; - ASC_DCNT saved_data_cnt; - PortAddr iop_base; - ushort sg_list_dwords; - ushort sg_index; - ushort sg_entry_cnt; - ushort q_addr; - uchar next_qp; - - iop_base = asc_dvc->iop_base; - sg_head = scsiq->sg_head; - saved_data_addr = scsiq->q1.data_addr; - saved_data_cnt = scsiq->q1.data_cnt; - scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr; - scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes; + int sta; + int i; + ASC_SG_HEAD *sg_head; + ASC_SG_LIST_Q scsi_sg_q; + ASC_DCNT saved_data_addr; + ASC_DCNT saved_data_cnt; + PortAddr iop_base; + ushort sg_list_dwords; + ushort sg_index; + ushort sg_entry_cnt; + ushort q_addr; + uchar next_qp; + + iop_base = asc_dvc->iop_base; + sg_head = scsiq->sg_head; + saved_data_addr = scsiq->q1.data_addr; + saved_data_cnt = scsiq->q1.data_cnt; + scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr; + scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes; #if CC_VERY_LONG_SG_LIST - /* - * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST - * then not all SG elements will fit in the allocated queues. - * The rest of the SG elements will be copied when the RISC - * completes the SG elements that fit and halts. - */ - if (sg_head->entry_cnt > ASC_MAX_SG_LIST) - { - /* - * Set sg_entry_cnt to be the number of SG elements that - * will fit in the allocated SG queues. It is minus 1, because - * the first SG element is handled above. ASC_MAX_SG_LIST is - * already inflated by 1 to account for this. For example it - * may be 50 which is 1 + 7 queues * 7 SG elements. - */ - sg_entry_cnt = ASC_MAX_SG_LIST - 1; - - /* - * Keep track of remaining number of SG elements that will - * need to be handled from a_isr.c. - */ - scsiq->remain_sg_entry_cnt = sg_head->entry_cnt - ASC_MAX_SG_LIST; - } else - { + /* + * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST + * then not all SG elements will fit in the allocated queues. + * The rest of the SG elements will be copied when the RISC + * completes the SG elements that fit and halts. + */ + if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { + /* + * Set sg_entry_cnt to be the number of SG elements that + * will fit in the allocated SG queues. It is minus 1, because + * the first SG element is handled above. ASC_MAX_SG_LIST is + * already inflated by 1 to account for this. For example it + * may be 50 which is 1 + 7 queues * 7 SG elements. + */ + sg_entry_cnt = ASC_MAX_SG_LIST - 1; + + /* + * Keep track of remaining number of SG elements that will + * need to be handled from a_isr.c. + */ + scsiq->remain_sg_entry_cnt = + sg_head->entry_cnt - ASC_MAX_SG_LIST; + } else { #endif /* CC_VERY_LONG_SG_LIST */ - /* - * Set sg_entry_cnt to be the number of SG elements that - * will fit in the allocated SG queues. It is minus 1, because - * the first SG element is handled above. - */ - sg_entry_cnt = sg_head->entry_cnt - 1; + /* + * Set sg_entry_cnt to be the number of SG elements that + * will fit in the allocated SG queues. It is minus 1, because + * the first SG element is handled above. + */ + sg_entry_cnt = sg_head->entry_cnt - 1; #if CC_VERY_LONG_SG_LIST - } + } #endif /* CC_VERY_LONG_SG_LIST */ - if (sg_entry_cnt != 0) { - scsiq->q1.cntl |= QC_SG_HEAD; - q_addr = ASC_QNO_TO_QADDR(q_no); - sg_index = 1; - scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; - scsi_sg_q.sg_head_qp = q_no; - scsi_sg_q.cntl = QCSG_SG_XFER_LIST; - for (i = 0; i < sg_head->queue_cnt; i++) { - scsi_sg_q.seq_no = i + 1; - if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { - sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2); - sg_entry_cnt -= ASC_SG_LIST_PER_Q; - if (i == 0) { - scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q; - scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q; - } else { - scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; - scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1; - } - } else { + if (sg_entry_cnt != 0) { + scsiq->q1.cntl |= QC_SG_HEAD; + q_addr = ASC_QNO_TO_QADDR(q_no); + sg_index = 1; + scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; + scsi_sg_q.sg_head_qp = q_no; + scsi_sg_q.cntl = QCSG_SG_XFER_LIST; + for (i = 0; i < sg_head->queue_cnt; i++) { + scsi_sg_q.seq_no = i + 1; + if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { + sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); + sg_entry_cnt -= ASC_SG_LIST_PER_Q; + if (i == 0) { + scsi_sg_q.sg_list_cnt = + ASC_SG_LIST_PER_Q; + scsi_sg_q.sg_cur_list_cnt = + ASC_SG_LIST_PER_Q; + } else { + scsi_sg_q.sg_list_cnt = + ASC_SG_LIST_PER_Q - 1; + scsi_sg_q.sg_cur_list_cnt = + ASC_SG_LIST_PER_Q - 1; + } + } else { #if CC_VERY_LONG_SG_LIST - /* - * This is the last SG queue in the list of - * allocated SG queues. If there are more - * SG elements than will fit in the allocated - * queues, then set the QCSG_SG_XFER_MORE flag. - */ - if (sg_head->entry_cnt > ASC_MAX_SG_LIST) - { - scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; - } else - { + /* + * This is the last SG queue in the list of + * allocated SG queues. If there are more + * SG elements than will fit in the allocated + * queues, then set the QCSG_SG_XFER_MORE flag. + */ + if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { + scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; + } else { #endif /* CC_VERY_LONG_SG_LIST */ - scsi_sg_q.cntl |= QCSG_SG_XFER_END; + scsi_sg_q.cntl |= QCSG_SG_XFER_END; #if CC_VERY_LONG_SG_LIST - } + } #endif /* CC_VERY_LONG_SG_LIST */ - sg_list_dwords = sg_entry_cnt << 1; - if (i == 0) { - scsi_sg_q.sg_list_cnt = sg_entry_cnt; - scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt; - } else { - scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; - scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; - } - sg_entry_cnt = 0; - } - next_qp = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_FWD)); - scsi_sg_q.q_no = next_qp; - q_addr = ASC_QNO_TO_QADDR(next_qp); - AscMemWordCopyPtrToLram(iop_base, - q_addr + ASC_SCSIQ_SGHD_CPY_BEG, - (uchar *) &scsi_sg_q, - sizeof(ASC_SG_LIST_Q) >> 1); - AscMemDWordCopyPtrToLram(iop_base, - q_addr + ASC_SGQ_LIST_BEG, - (uchar *) &sg_head->sg_list[sg_index], - sg_list_dwords); - sg_index += ASC_SG_LIST_PER_Q; - scsiq->next_sg_index = sg_index; - } - } else { - scsiq->q1.cntl &= ~QC_SG_HEAD; - } - sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); - scsiq->q1.data_addr = saved_data_addr; - scsiq->q1.data_cnt = saved_data_cnt; - return (sta); + sg_list_dwords = sg_entry_cnt << 1; + if (i == 0) { + scsi_sg_q.sg_list_cnt = sg_entry_cnt; + scsi_sg_q.sg_cur_list_cnt = + sg_entry_cnt; + } else { + scsi_sg_q.sg_list_cnt = + sg_entry_cnt - 1; + scsi_sg_q.sg_cur_list_cnt = + sg_entry_cnt - 1; + } + sg_entry_cnt = 0; + } + next_qp = AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_FWD)); + scsi_sg_q.q_no = next_qp; + q_addr = ASC_QNO_TO_QADDR(next_qp); + AscMemWordCopyPtrToLram(iop_base, + q_addr + ASC_SCSIQ_SGHD_CPY_BEG, + (uchar *)&scsi_sg_q, + sizeof(ASC_SG_LIST_Q) >> 1); + AscMemDWordCopyPtrToLram(iop_base, + q_addr + ASC_SGQ_LIST_BEG, + (uchar *)&sg_head-> + sg_list[sg_index], + sg_list_dwords); + sg_index += ASC_SG_LIST_PER_Q; + scsiq->next_sg_index = sg_index; + } + } else { + scsiq->q1.cntl &= ~QC_SG_HEAD; + } + sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); + scsiq->q1.data_addr = saved_data_addr; + scsiq->q1.data_cnt = saved_data_cnt; + return (sta); } -STATIC int -AscSetRunChipSynRegAtID( - PortAddr iop_base, - uchar tid_no, - uchar sdtr_data -) +static int +AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data) { - int sta = FALSE; + int sta = FALSE; - if (AscHostReqRiscHalt(iop_base)) { - sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); - AscStartChip(iop_base); - return (sta); - } - return (sta); + if (AscHostReqRiscHalt(iop_base)) { + sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); + AscStartChip(iop_base); + return (sta); + } + return (sta); } -STATIC int -AscSetChipSynRegAtID( - PortAddr iop_base, - uchar id, - uchar sdtr_data -) +static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data) { - ASC_SCSI_BIT_ID_TYPE org_id; - int i; - int sta = TRUE; - - AscSetBank(iop_base, 1); - org_id = AscReadChipDvcID(iop_base); - for (i = 0; i <= ASC_MAX_TID; i++) { - if (org_id == (0x01 << i)) - break; - } - org_id = (ASC_SCSI_BIT_ID_TYPE) i; - AscWriteChipDvcID(iop_base, id); - if (AscReadChipDvcID(iop_base) == (0x01 << id)) { - AscSetBank(iop_base, 0); - AscSetChipSyn(iop_base, sdtr_data); - if (AscGetChipSyn(iop_base) != sdtr_data) { - sta = FALSE; - } - } else { - sta = FALSE; - } - AscSetBank(iop_base, 1); - AscWriteChipDvcID(iop_base, org_id); - AscSetBank(iop_base, 0); - return (sta); + ASC_SCSI_BIT_ID_TYPE org_id; + int i; + int sta = TRUE; + + AscSetBank(iop_base, 1); + org_id = AscReadChipDvcID(iop_base); + for (i = 0; i <= ASC_MAX_TID; i++) { + if (org_id == (0x01 << i)) + break; + } + org_id = (ASC_SCSI_BIT_ID_TYPE) i; + AscWriteChipDvcID(iop_base, id); + if (AscReadChipDvcID(iop_base) == (0x01 << id)) { + AscSetBank(iop_base, 0); + AscSetChipSyn(iop_base, sdtr_data); + if (AscGetChipSyn(iop_base) != sdtr_data) { + sta = FALSE; + } + } else { + sta = FALSE; + } + AscSetBank(iop_base, 1); + AscWriteChipDvcID(iop_base, org_id); + AscSetBank(iop_base, 0); + return (sta); } -STATIC ushort -AscInitLram( - ASC_DVC_VAR *asc_dvc -) +static ushort AscInitLram(ASC_DVC_VAR *asc_dvc) { - uchar i; - ushort s_addr; - PortAddr iop_base; - ushort warn_code; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, - (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1) -); - i = ASC_MIN_ACTIVE_QNO; - s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), - (uchar) (i + 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), - (uchar) (asc_dvc->max_total_qng)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), - (uchar) i); - i++; - s_addr += ASC_QBLK_SIZE; - for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), - (uchar) (i + 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), - (uchar) (i - 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), - (uchar) i); - } - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), - (uchar) ASC_QLINK_END); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), - (uchar) (asc_dvc->max_total_qng - 1)); - AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), - (uchar) asc_dvc->max_total_qng); - i++; - s_addr += ASC_QBLK_SIZE; - for (; i <= (uchar) (asc_dvc->max_total_qng + 3); - i++, s_addr += ASC_QBLK_SIZE) { - AscWriteLramByte(iop_base, - (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i); - AscWriteLramByte(iop_base, - (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i); - AscWriteLramByte(iop_base, - (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i); - } - return (warn_code); + uchar i; + ushort s_addr; + PortAddr iop_base; + ushort warn_code; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, + (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) * + 64) >> 1) + ); + i = ASC_MIN_ACTIVE_QNO; + s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), + (uchar)(i + 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), + (uchar)(asc_dvc->max_total_qng)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), + (uchar)i); + i++; + s_addr += ASC_QBLK_SIZE; + for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), + (uchar)(i + 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), + (uchar)(i - 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), + (uchar)i); + } + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), + (uchar)ASC_QLINK_END); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), + (uchar)(asc_dvc->max_total_qng - 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), + (uchar)asc_dvc->max_total_qng); + i++; + s_addr += ASC_QBLK_SIZE; + for (; i <= (uchar)(asc_dvc->max_total_qng + 3); + i++, s_addr += ASC_QBLK_SIZE) { + AscWriteLramByte(iop_base, + (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i); + AscWriteLramByte(iop_base, + (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i); + AscWriteLramByte(iop_base, + (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i); + } + return (warn_code); } -STATIC ushort -AscInitQLinkVar( - ASC_DVC_VAR *asc_dvc -) +static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc) { - PortAddr iop_base; - int i; - ushort lram_addr; - - iop_base = asc_dvc->iop_base; - AscPutRiscVarFreeQHead(iop_base, 1); - AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); - AscPutVarFreeQHead(iop_base, 1); - AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); - AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, - (uchar) ((int) asc_dvc->max_total_qng + 1)); - AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, - (uchar) ((int) asc_dvc->max_total_qng + 2)); - AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B, - asc_dvc->max_total_qng); - AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); - AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); - AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); - AscPutQDoneInProgress(iop_base, 0); - lram_addr = ASC_QADR_BEG; - for (i = 0; i < 32; i++, lram_addr += 2) { - AscWriteLramWord(iop_base, lram_addr, 0); - } - return (0); + PortAddr iop_base; + int i; + ushort lram_addr; + + iop_base = asc_dvc->iop_base; + AscPutRiscVarFreeQHead(iop_base, 1); + AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); + AscPutVarFreeQHead(iop_base, 1); + AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); + AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, + (uchar)((int)asc_dvc->max_total_qng + 1)); + AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, + (uchar)((int)asc_dvc->max_total_qng + 2)); + AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B, + asc_dvc->max_total_qng); + AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); + AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); + AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); + AscPutQDoneInProgress(iop_base, 0); + lram_addr = ASC_QADR_BEG; + for (i = 0; i < 32; i++, lram_addr += 2) { + AscWriteLramWord(iop_base, lram_addr, 0); + } + return (0); } -STATIC int -AscSetLibErrorCode( - ASC_DVC_VAR *asc_dvc, - ushort err_code -) +static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code) { - if (asc_dvc->err_code == 0) { - asc_dvc->err_code = err_code; - AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, - err_code); - } - return (err_code); + if (asc_dvc->err_code == 0) { + asc_dvc->err_code = err_code; + AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, + err_code); + } + return (err_code); } - -STATIC uchar -AscMsgOutSDTR( - ASC_DVC_VAR *asc_dvc, - uchar sdtr_period, - uchar sdtr_offset -) +static uchar +AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset) { - EXT_MSG sdtr_buf; - uchar sdtr_period_index; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - sdtr_buf.msg_type = MS_EXTEND; - sdtr_buf.msg_len = MS_SDTR_LEN; - sdtr_buf.msg_req = MS_SDTR_CODE; - sdtr_buf.xfer_period = sdtr_period; - sdtr_offset &= ASC_SYN_MAX_OFFSET; - sdtr_buf.req_ack_offset = sdtr_offset; - if ((sdtr_period_index = - AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <= - asc_dvc->max_sdtr_index) { - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &sdtr_buf, - sizeof (EXT_MSG) >> 1); - return ((sdtr_period_index << 4) | sdtr_offset); - } else { - - sdtr_buf.req_ack_offset = 0; - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *) &sdtr_buf, - sizeof (EXT_MSG) >> 1); - return (0); - } + EXT_MSG sdtr_buf; + uchar sdtr_period_index; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + sdtr_buf.msg_type = MS_EXTEND; + sdtr_buf.msg_len = MS_SDTR_LEN; + sdtr_buf.msg_req = MS_SDTR_CODE; + sdtr_buf.xfer_period = sdtr_period; + sdtr_offset &= ASC_SYN_MAX_OFFSET; + sdtr_buf.req_ack_offset = sdtr_offset; + if ((sdtr_period_index = + AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <= + asc_dvc->max_sdtr_index) { + AscMemWordCopyPtrToLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&sdtr_buf, + sizeof(EXT_MSG) >> 1); + return ((sdtr_period_index << 4) | sdtr_offset); + } else { + + sdtr_buf.req_ack_offset = 0; + AscMemWordCopyPtrToLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&sdtr_buf, + sizeof(EXT_MSG) >> 1); + return (0); + } } -STATIC uchar -AscCalSDTRData( - ASC_DVC_VAR *asc_dvc, - uchar sdtr_period, - uchar syn_offset -) +static uchar +AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset) { - uchar byte; - uchar sdtr_period_ix; - - sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period); - if ( - (sdtr_period_ix > asc_dvc->max_sdtr_index) -) { - return (0xFF); - } - byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); - return (byte); + uchar byte; + uchar sdtr_period_ix; + + sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period); + if ((sdtr_period_ix > asc_dvc->max_sdtr_index) + ) { + return (0xFF); + } + byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); + return (byte); } -STATIC void -AscSetChipSDTR( - PortAddr iop_base, - uchar sdtr_data, - uchar tid_no -) +static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no) { - AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); - AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data); - return; + AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); + AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data); + return; } -STATIC uchar -AscGetSynPeriodIndex( - ASC_DVC_VAR *asc_dvc, - uchar syn_time -) +static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time) { - uchar *period_table; - int max_index; - int min_index; - int i; - - period_table = asc_dvc->sdtr_period_tbl; - max_index = (int) asc_dvc->max_sdtr_index; - min_index = (int)asc_dvc->host_init_sdtr_index; - if ((syn_time <= period_table[max_index])) { - for (i = min_index; i < (max_index - 1); i++) { - if (syn_time <= period_table[i]) { - return ((uchar) i); - } - } - return ((uchar) max_index); - } else { - return ((uchar) (max_index + 1)); - } + uchar *period_table; + int max_index; + int min_index; + int i; + + period_table = asc_dvc->sdtr_period_tbl; + max_index = (int)asc_dvc->max_sdtr_index; + min_index = (int)asc_dvc->host_init_sdtr_index; + if ((syn_time <= period_table[max_index])) { + for (i = min_index; i < (max_index - 1); i++) { + if (syn_time <= period_table[i]) { + return ((uchar)i); + } + } + return ((uchar)max_index); + } else { + return ((uchar)(max_index + 1)); + } } -STATIC uchar -AscAllocFreeQueue( - PortAddr iop_base, - uchar free_q_head -) +static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head) { - ushort q_addr; - uchar next_qp; - uchar q_status; - - q_addr = ASC_QNO_TO_QADDR(free_q_head); - q_status = (uchar) AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_STATUS)); - next_qp = AscReadLramByte(iop_base, - (ushort) (q_addr + ASC_SCSIQ_B_FWD)); - if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) { - return (next_qp); - } - return (ASC_QLINK_END); + ushort q_addr; + uchar next_qp; + uchar q_status; + + q_addr = ASC_QNO_TO_QADDR(free_q_head); + q_status = (uchar)AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_STATUS)); + next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD)); + if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) { + return (next_qp); + } + return (ASC_QLINK_END); } -STATIC uchar -AscAllocMultipleFreeQueue( - PortAddr iop_base, - uchar free_q_head, - uchar n_free_q -) +static uchar +AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q) { - uchar i; + uchar i; - for (i = 0; i < n_free_q; i++) { - if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head)) - == ASC_QLINK_END) { - return (ASC_QLINK_END); - } - } - return (free_q_head); + for (i = 0; i < n_free_q; i++) { + if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head)) + == ASC_QLINK_END) { + return (ASC_QLINK_END); + } + } + return (free_q_head); } -STATIC int -AscHostReqRiscHalt( - PortAddr iop_base -) +static int AscHostReqRiscHalt(PortAddr iop_base) { - int count = 0; - int sta = 0; - uchar saved_stop_code; - - if (AscIsChipHalted(iop_base)) - return (1); - saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP -); - do { - if (AscIsChipHalted(iop_base)) { - sta = 1; - break; - } - DvcSleepMilliSecond(100); - } while (count++ < 20); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); - return (sta); + int count = 0; + int sta = 0; + uchar saved_stop_code; + + if (AscIsChipHalted(iop_base)) + return (1); + saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP); + do { + if (AscIsChipHalted(iop_base)) { + sta = 1; + break; + } + DvcSleepMilliSecond(100); + } while (count++ < 20); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); + return (sta); } -STATIC int -AscStopQueueExe( - PortAddr iop_base -) +static int AscStopQueueExe(PortAddr iop_base) { - int count = 0; - - if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_REQ_RISC_STOP); - do { - if ( - AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & - ASC_STOP_ACK_RISC_STOP) { - return (1); - } - DvcSleepMilliSecond(100); - } while (count++ < 20); - } - return (0); + int count = 0; + + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_REQ_RISC_STOP); + do { + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & + ASC_STOP_ACK_RISC_STOP) { + return (1); + } + DvcSleepMilliSecond(100); + } while (count++ < 20); + } + return (0); } -STATIC void -DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec) +static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec) { - udelay(micro_sec); + udelay(micro_sec); } -STATIC void -DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec) +static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec) { - udelay((nano_sec + 999)/1000); + udelay((nano_sec + 999) / 1000); } #ifdef CONFIG_ISA -STATIC ASC_DCNT __init -AscGetEisaProductID( - PortAddr iop_base) +static ASC_DCNT __init AscGetEisaProductID(PortAddr iop_base) { - PortAddr eisa_iop; - ushort product_id_high, product_id_low; - ASC_DCNT product_id; - - eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK; - product_id_low = inpw(eisa_iop); - product_id_high = inpw(eisa_iop + 2); - product_id = ((ASC_DCNT) product_id_high << 16) | - (ASC_DCNT) product_id_low; - return (product_id); + PortAddr eisa_iop; + ushort product_id_high, product_id_low; + ASC_DCNT product_id; + + eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK; + product_id_low = inpw(eisa_iop); + product_id_high = inpw(eisa_iop + 2); + product_id = ((ASC_DCNT) product_id_high << 16) | + (ASC_DCNT) product_id_low; + return (product_id); } -STATIC PortAddr __init -AscSearchIOPortAddrEISA( - PortAddr iop_base) +static PortAddr __init AscSearchIOPortAddrEISA(PortAddr iop_base) { - ASC_DCNT eisa_product_id; - - if (iop_base == 0) { - iop_base = ASC_EISA_MIN_IOP_ADDR; - } else { - if (iop_base == ASC_EISA_MAX_IOP_ADDR) - return (0); - if ((iop_base & 0x0050) == 0x0050) { - iop_base += ASC_EISA_BIG_IOP_GAP; - } else { - iop_base += ASC_EISA_SMALL_IOP_GAP; - } - } - while (iop_base <= ASC_EISA_MAX_IOP_ADDR) { - eisa_product_id = AscGetEisaProductID(iop_base); - if ((eisa_product_id == ASC_EISA_ID_740) || - (eisa_product_id == ASC_EISA_ID_750)) { - if (AscFindSignature(iop_base)) { - inpw(iop_base + 4); - return (iop_base); - } - } - if (iop_base == ASC_EISA_MAX_IOP_ADDR) - return (0); - if ((iop_base & 0x0050) == 0x0050) { - iop_base += ASC_EISA_BIG_IOP_GAP; - } else { - iop_base += ASC_EISA_SMALL_IOP_GAP; - } - } - return (0); + ASC_DCNT eisa_product_id; + + if (iop_base == 0) { + iop_base = ASC_EISA_MIN_IOP_ADDR; + } else { + if (iop_base == ASC_EISA_MAX_IOP_ADDR) + return (0); + if ((iop_base & 0x0050) == 0x0050) { + iop_base += ASC_EISA_BIG_IOP_GAP; + } else { + iop_base += ASC_EISA_SMALL_IOP_GAP; + } + } + while (iop_base <= ASC_EISA_MAX_IOP_ADDR) { + eisa_product_id = AscGetEisaProductID(iop_base); + if ((eisa_product_id == ASC_EISA_ID_740) || + (eisa_product_id == ASC_EISA_ID_750)) { + if (AscFindSignature(iop_base)) { + inpw(iop_base + 4); + return (iop_base); + } + } + if (iop_base == ASC_EISA_MAX_IOP_ADDR) + return (0); + if ((iop_base & 0x0050) == 0x0050) { + iop_base += ASC_EISA_BIG_IOP_GAP; + } else { + iop_base += ASC_EISA_SMALL_IOP_GAP; + } + } + return (0); } #endif /* CONFIG_ISA */ -STATIC int -AscStartChip( - PortAddr iop_base -) +static int AscStartChip(PortAddr iop_base) { - AscSetChipControl(iop_base, 0); - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - return (0); - } - return (1); + AscSetChipControl(iop_base, 0); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + return (0); + } + return (1); } -STATIC int -AscStopChip( - PortAddr iop_base -) +static int AscStopChip(PortAddr iop_base) { - uchar cc_val; - - cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); - AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT)); - AscSetChipIH(iop_base, INS_HALT); - AscSetChipIH(iop_base, INS_RFLAG_WTM); - if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { - return (0); - } - return (1); + uchar cc_val; + + cc_val = + AscGetChipControl(iop_base) & + (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); + AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT)); + AscSetChipIH(iop_base, INS_HALT); + AscSetChipIH(iop_base, INS_RFLAG_WTM); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { + return (0); + } + return (1); } -STATIC int -AscIsChipHalted( - PortAddr iop_base -) +static int AscIsChipHalted(PortAddr iop_base) { - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { - return (1); - } - } - return (0); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { + return (1); + } + } + return (0); } -STATIC void -AscSetChipIH( - PortAddr iop_base, - ushort ins_code -) +static void AscSetChipIH(PortAddr iop_base, ushort ins_code) { - AscSetBank(iop_base, 1); - AscWriteChipIH(iop_base, ins_code); - AscSetBank(iop_base, 0); - return; + AscSetBank(iop_base, 1); + AscWriteChipIH(iop_base, ins_code); + AscSetBank(iop_base, 0); + return; } -STATIC void -AscAckInterrupt( - PortAddr iop_base -) +static void AscAckInterrupt(PortAddr iop_base) { - uchar host_flag; - uchar risc_flag; - ushort loop; - - loop = 0; - do { - risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); - if (loop++ > 0x7FFF) { - break; - } - } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); - host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT); - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, - (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT)); - AscSetChipStatus(iop_base, CIW_INT_ACK); - loop = 0; - while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { - AscSetChipStatus(iop_base, CIW_INT_ACK); - if (loop++ > 3) { - break; - } - } - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); - return; + uchar host_flag; + uchar risc_flag; + ushort loop; + + loop = 0; + do { + risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); + if (loop++ > 0x7FFF) { + break; + } + } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); + host_flag = + AscReadLramByte(iop_base, + ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT); + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, + (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT)); + AscSetChipStatus(iop_base, CIW_INT_ACK); + loop = 0; + while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { + AscSetChipStatus(iop_base, CIW_INT_ACK); + if (loop++ > 3) { + break; + } + } + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); + return; } -STATIC void -AscDisableInterrupt( - PortAddr iop_base -) +static void AscDisableInterrupt(PortAddr iop_base) { - ushort cfg; + ushort cfg; - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); - return; + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); + return; } -STATIC void -AscEnableInterrupt( - PortAddr iop_base -) +static void AscEnableInterrupt(PortAddr iop_base) { - ushort cfg; + ushort cfg; - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); - return; + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); + return; } - - -STATIC void -AscSetBank( - PortAddr iop_base, - uchar bank -) +static void AscSetBank(PortAddr iop_base, uchar bank) { - uchar val; - - val = AscGetChipControl(iop_base) & - (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET)); - if (bank == 1) { - val |= CC_BANK_ONE; - } else if (bank == 2) { - val |= CC_DIAG | CC_BANK_ONE; - } else { - val &= ~CC_BANK_ONE; - } - AscSetChipControl(iop_base, val); - return; + uchar val; + + val = AscGetChipControl(iop_base) & + (~ + (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | + CC_CHIP_RESET)); + if (bank == 1) { + val |= CC_BANK_ONE; + } else if (bank == 2) { + val |= CC_DIAG | CC_BANK_ONE; + } else { + val &= ~CC_BANK_ONE; + } + AscSetChipControl(iop_base, val); + return; } -STATIC int -AscResetChipAndScsiBus( - ASC_DVC_VAR *asc_dvc -) +static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc) { - PortAddr iop_base; - int i = 10; + PortAddr iop_base; + int i = 10; - iop_base = asc_dvc->iop_base; - while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) - { - DvcSleepMilliSecond(100); - } - AscStopChip(iop_base); - AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); - DvcDelayNanoSecond(asc_dvc, 60000); - AscSetChipIH(iop_base, INS_RFLAG_WTM); - AscSetChipIH(iop_base, INS_HALT); - AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); - AscSetChipControl(iop_base, CC_HALT); - DvcSleepMilliSecond(200); - AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); - AscSetChipStatus(iop_base, 0); - return (AscIsChipHalted(iop_base)); + iop_base = asc_dvc->iop_base; + while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) + && (i-- > 0)) { + DvcSleepMilliSecond(100); + } + AscStopChip(iop_base); + AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); + DvcDelayNanoSecond(asc_dvc, 60000); + AscSetChipIH(iop_base, INS_RFLAG_WTM); + AscSetChipIH(iop_base, INS_HALT); + AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); + AscSetChipControl(iop_base, CC_HALT); + DvcSleepMilliSecond(200); + AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); + AscSetChipStatus(iop_base, 0); + return (AscIsChipHalted(iop_base)); } -STATIC ASC_DCNT __init -AscGetMaxDmaCount( - ushort bus_type) +static ASC_DCNT __init AscGetMaxDmaCount(ushort bus_type) { - if (bus_type & ASC_IS_ISA) - return (ASC_MAX_ISA_DMA_COUNT); - else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) - return (ASC_MAX_VL_DMA_COUNT); - return (ASC_MAX_PCI_DMA_COUNT); + if (bus_type & ASC_IS_ISA) + return (ASC_MAX_ISA_DMA_COUNT); + else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) + return (ASC_MAX_VL_DMA_COUNT); + return (ASC_MAX_PCI_DMA_COUNT); } #ifdef CONFIG_ISA -STATIC ushort __init -AscGetIsaDmaChannel( - PortAddr iop_base) +static ushort __init AscGetIsaDmaChannel(PortAddr iop_base) { - ushort channel; - - channel = AscGetChipCfgLsw(iop_base) & 0x0003; - if (channel == 0x03) - return (0); - else if (channel == 0x00) - return (7); - return (channel + 4); + ushort channel; + + channel = AscGetChipCfgLsw(iop_base) & 0x0003; + if (channel == 0x03) + return (0); + else if (channel == 0x00) + return (7); + return (channel + 4); } -STATIC ushort __init -AscSetIsaDmaChannel( - PortAddr iop_base, - ushort dma_channel) +static ushort __init AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel) { - ushort cfg_lsw; - uchar value; - - if ((dma_channel >= 5) && (dma_channel <= 7)) { - if (dma_channel == 7) - value = 0x00; - else - value = dma_channel - 4; - cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; - cfg_lsw |= value; - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetIsaDmaChannel(iop_base)); - } - return (0); + ushort cfg_lsw; + uchar value; + + if ((dma_channel >= 5) && (dma_channel <= 7)) { + if (dma_channel == 7) + value = 0x00; + else + value = dma_channel - 4; + cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; + cfg_lsw |= value; + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetIsaDmaChannel(iop_base)); + } + return (0); } -STATIC uchar __init -AscSetIsaDmaSpeed( - PortAddr iop_base, - uchar speed_value) +static uchar __init AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value) { - speed_value &= 0x07; - AscSetBank(iop_base, 1); - AscWriteChipDmaSpeed(iop_base, speed_value); - AscSetBank(iop_base, 0); - return (AscGetIsaDmaSpeed(iop_base)); + speed_value &= 0x07; + AscSetBank(iop_base, 1); + AscWriteChipDmaSpeed(iop_base, speed_value); + AscSetBank(iop_base, 0); + return (AscGetIsaDmaSpeed(iop_base)); } -STATIC uchar __init -AscGetIsaDmaSpeed( - PortAddr iop_base -) +static uchar __init AscGetIsaDmaSpeed(PortAddr iop_base) { - uchar speed_value; + uchar speed_value; - AscSetBank(iop_base, 1); - speed_value = AscReadChipDmaSpeed(iop_base); - speed_value &= 0x07; - AscSetBank(iop_base, 0); - return (speed_value); + AscSetBank(iop_base, 1); + speed_value = AscReadChipDmaSpeed(iop_base); + speed_value &= 0x07; + AscSetBank(iop_base, 0); + return (speed_value); } #endif /* CONFIG_ISA */ -STATIC ushort __init -AscReadPCIConfigWord( - ASC_DVC_VAR *asc_dvc, - ushort pci_config_offset) +static ushort __init +AscReadPCIConfigWord(ASC_DVC_VAR *asc_dvc, ushort pci_config_offset) { - uchar lsb, msb; + uchar lsb, msb; - lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset); - msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1); - return ((ushort) ((msb << 8) | lsb)); + lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset); + msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1); + return ((ushort)((msb << 8) | lsb)); } -STATIC ushort __init -AscInitGetConfig( - ASC_DVC_VAR *asc_dvc -) +static ushort __init AscInitGetConfig(ASC_DVC_VAR *asc_dvc) { - ushort warn_code; - PortAddr iop_base; - ushort PCIDeviceID; - ushort PCIVendorID; - uchar PCIRevisionID; - uchar prevCmdRegBits; - - warn_code = 0; - iop_base = asc_dvc->iop_base; - asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; - if (asc_dvc->err_code != 0) { - return (UW_ERR); - } - if (asc_dvc->bus_type == ASC_IS_PCI) { - PCIVendorID = AscReadPCIConfigWord(asc_dvc, - AscPCIConfigVendorIDRegister); - - PCIDeviceID = AscReadPCIConfigWord(asc_dvc, - AscPCIConfigDeviceIDRegister); - - PCIRevisionID = DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigRevisionIDRegister); - - if (PCIVendorID != PCI_VENDOR_ID_ASP) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister); - - if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) != - AscPCICmdRegBits_IOMemBusMaster) { - DvcWritePCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister, - (prevCmdRegBits | - AscPCICmdRegBits_IOMemBusMaster)); - - if ((DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister) - & AscPCICmdRegBits_IOMemBusMaster) - != AscPCICmdRegBits_IOMemBusMaster) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - if ((PCIDeviceID == PCI_DEVICE_ID_ASP_1200A) || - (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940)) { - DvcWritePCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer, 0x00); - if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) - != 0x00) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } else if (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940U) { - if (DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer) < 0x20) { - DvcWritePCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer, 0x20); - - if (DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer) < 0x20) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - } - } + ushort warn_code; + PortAddr iop_base; + ushort PCIDeviceID; + ushort PCIVendorID; + uchar PCIRevisionID; + uchar prevCmdRegBits; + + warn_code = 0; + iop_base = asc_dvc->iop_base; + asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; + if (asc_dvc->err_code != 0) { + return (UW_ERR); + } + if (asc_dvc->bus_type == ASC_IS_PCI) { + PCIVendorID = AscReadPCIConfigWord(asc_dvc, + AscPCIConfigVendorIDRegister); + + PCIDeviceID = AscReadPCIConfigWord(asc_dvc, + AscPCIConfigDeviceIDRegister); + + PCIRevisionID = DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigRevisionIDRegister); + + if (PCIVendorID != PCI_VENDOR_ID_ASP) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister); + + if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) != + AscPCICmdRegBits_IOMemBusMaster) { + DvcWritePCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister, + (prevCmdRegBits | + AscPCICmdRegBits_IOMemBusMaster)); + + if ((DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister) + & AscPCICmdRegBits_IOMemBusMaster) + != AscPCICmdRegBits_IOMemBusMaster) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } + if ((PCIDeviceID == PCI_DEVICE_ID_ASP_1200A) || + (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940)) { + DvcWritePCIConfigByte(asc_dvc, + AscPCIConfigLatencyTimer, 0x00); + if (DvcReadPCIConfigByte + (asc_dvc, AscPCIConfigLatencyTimer) + != 0x00) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } else if (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940U) { + if (DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigLatencyTimer) < + 0x20) { + DvcWritePCIConfigByte(asc_dvc, + AscPCIConfigLatencyTimer, + 0x20); + + if (DvcReadPCIConfigByte(asc_dvc, + AscPCIConfigLatencyTimer) + < 0x20) { + warn_code |= + ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } + } + } - if (AscFindSignature(iop_base)) { - warn_code |= AscInitAscDvcVar(asc_dvc); - warn_code |= AscInitFromEEP(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; - if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) { - asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT; - } - } else { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - } - return(warn_code); + if (AscFindSignature(iop_base)) { + warn_code |= AscInitAscDvcVar(asc_dvc); + warn_code |= AscInitFromEEP(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; + if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) { + asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT; + } + } else { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + } + return (warn_code); } -STATIC ushort __init -AscInitSetConfig( - ASC_DVC_VAR *asc_dvc -) +static ushort __init AscInitSetConfig(ASC_DVC_VAR *asc_dvc) { - ushort warn_code = 0; - - asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; - if (asc_dvc->err_code != 0) - return (UW_ERR); - if (AscFindSignature(asc_dvc->iop_base)) { - warn_code |= AscInitFromAscDvcVar(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; - } else { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - } - return (warn_code); + ushort warn_code = 0; + + asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; + if (asc_dvc->err_code != 0) + return (UW_ERR); + if (AscFindSignature(asc_dvc->iop_base)) { + warn_code |= AscInitFromAscDvcVar(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; + } else { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + } + return (warn_code); } -STATIC ushort __init -AscInitFromAscDvcVar( - ASC_DVC_VAR *asc_dvc -) +static ushort __init AscInitFromAscDvcVar(ASC_DVC_VAR *asc_dvc) { - PortAddr iop_base; - ushort cfg_msw; - ushort warn_code; - ushort pci_device_id = 0; + PortAddr iop_base; + ushort cfg_msw; + ushort warn_code; + ushort pci_device_id = 0; - iop_base = asc_dvc->iop_base; + iop_base = asc_dvc->iop_base; #ifdef CONFIG_PCI - if (asc_dvc->cfg->dev) - pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device; + if (asc_dvc->cfg->dev) + pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device; #endif - warn_code = 0; - cfg_msw = AscGetChipCfgMsw(iop_base); - if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { - cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); - warn_code |= ASC_WARN_CFG_MSW_RECOVER; - AscSetChipCfgMsw(iop_base, cfg_msw); - } - if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != - asc_dvc->cfg->cmd_qng_enabled) { - asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; - warn_code |= ASC_WARN_CMD_QNG_CONFLICT; - } - if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { - warn_code |= ASC_WARN_AUTO_CONFIG; - } - if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { - if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) - != asc_dvc->irq_no) { - asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; - } - } - if (asc_dvc->bus_type & ASC_IS_PCI) { - cfg_msw &= 0xFFC0; - AscSetChipCfgMsw(iop_base, cfg_msw); - if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { - } else { - if ((pci_device_id == PCI_DEVICE_ID_ASP_1200A) || - (pci_device_id == PCI_DEVICE_ID_ASP_ABP940)) { - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; - } - } - } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) { - if (AscGetChipVersion(iop_base, asc_dvc->bus_type) - == ASC_CHIP_VER_ASYN_BUG) { - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; - } - } - if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != - asc_dvc->cfg->chip_scsi_id) { - asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; - } + warn_code = 0; + cfg_msw = AscGetChipCfgMsw(iop_base); + if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { + cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); + warn_code |= ASC_WARN_CFG_MSW_RECOVER; + AscSetChipCfgMsw(iop_base, cfg_msw); + } + if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != + asc_dvc->cfg->cmd_qng_enabled) { + asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; + warn_code |= ASC_WARN_CMD_QNG_CONFLICT; + } + if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { + warn_code |= ASC_WARN_AUTO_CONFIG; + } + if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { + if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) + != asc_dvc->irq_no) { + asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; + } + } + if (asc_dvc->bus_type & ASC_IS_PCI) { + cfg_msw &= 0xFFC0; + AscSetChipCfgMsw(iop_base, cfg_msw); + if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { + } else { + if ((pci_device_id == PCI_DEVICE_ID_ASP_1200A) || + (pci_device_id == PCI_DEVICE_ID_ASP_ABP940)) { + asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; + asc_dvc->bug_fix_cntl |= + ASC_BUG_FIX_ASYN_USE_SYN; + } + } + } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) { + if (AscGetChipVersion(iop_base, asc_dvc->bus_type) + == ASC_CHIP_VER_ASYN_BUG) { + asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; + } + } + if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != + asc_dvc->cfg->chip_scsi_id) { + asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; + } #ifdef CONFIG_ISA - if (asc_dvc->bus_type & ASC_IS_ISA) { - AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); - AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); - } + if (asc_dvc->bus_type & ASC_IS_ISA) { + AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); + AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); + } #endif /* CONFIG_ISA */ - return (warn_code); + return (warn_code); } -STATIC ushort -AscInitAsc1000Driver( - ASC_DVC_VAR *asc_dvc -) +static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) { - ushort warn_code; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && - !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { - AscResetChipAndScsiBus(asc_dvc); - DvcSleepMilliSecond((ASC_DCNT) - ((ushort) asc_dvc->scsi_reset_wait * 1000)); - } - asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; - if (asc_dvc->err_code != 0) - return (UW_ERR); - if (!AscFindSignature(asc_dvc->iop_base)) { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - return (warn_code); - } - AscDisableInterrupt(iop_base); - warn_code |= AscInitLram(asc_dvc); - if (asc_dvc->err_code != 0) - return (UW_ERR); - ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n", - (ulong) _asc_mcode_chksum); - if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf, - _asc_mcode_size) != _asc_mcode_chksum) { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return (warn_code); - } - warn_code |= AscInitMicroCodeVar(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; - AscEnableInterrupt(iop_base); - return (warn_code); + ushort warn_code; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && + !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { + AscResetChipAndScsiBus(asc_dvc); + DvcSleepMilliSecond((ASC_DCNT) + ((ushort)asc_dvc->scsi_reset_wait * 1000)); + } + asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; + if (asc_dvc->err_code != 0) + return (UW_ERR); + if (!AscFindSignature(asc_dvc->iop_base)) { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + return (warn_code); + } + AscDisableInterrupt(iop_base); + warn_code |= AscInitLram(asc_dvc); + if (asc_dvc->err_code != 0) + return (UW_ERR); + ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n", + (ulong)_asc_mcode_chksum); + if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf, + _asc_mcode_size) != _asc_mcode_chksum) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return (warn_code); + } + warn_code |= AscInitMicroCodeVar(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; + AscEnableInterrupt(iop_base); + return (warn_code); } -STATIC ushort __init -AscInitAscDvcVar( - ASC_DVC_VAR *asc_dvc) +static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) { - int i; - PortAddr iop_base; - ushort warn_code; - uchar chip_version; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - asc_dvc->err_code = 0; - if ((asc_dvc->bus_type & - (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) { - asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE; - } - AscSetChipControl(iop_base, CC_HALT); - AscSetChipStatus(iop_base, 0); - asc_dvc->bug_fix_cntl = 0; - asc_dvc->pci_fix_asyn_xfer = 0; - asc_dvc->pci_fix_asyn_xfer_always = 0; - /* asc_dvc->init_state initalized in AscInitGetConfig(). */ - asc_dvc->sdtr_done = 0; - asc_dvc->cur_total_qng = 0; - asc_dvc->is_in_int = 0; - asc_dvc->in_critical_cnt = 0; - asc_dvc->last_q_shortage = 0; - asc_dvc->use_tagged_qng = 0; - asc_dvc->no_scam = 0; - asc_dvc->unit_not_ready = 0; - asc_dvc->queue_full_or_busy = 0; - asc_dvc->redo_scam = 0; - asc_dvc->res2 = 0; - asc_dvc->host_init_sdtr_index = 0; - asc_dvc->cfg->can_tagged_qng = 0; - asc_dvc->cfg->cmd_qng_enabled = 0; - asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; - asc_dvc->init_sdtr = 0; - asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; - asc_dvc->scsi_reset_wait = 3; - asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); - asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; - asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; - asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; - asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | - ASC_LIB_VERSION_MINOR; - chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type); - asc_dvc->cfg->chip_version = chip_version; - asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0; - asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1; - asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2; - asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3; - asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4; - asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5; - asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6; - asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7; - asc_dvc->max_sdtr_index = 7; - if ((asc_dvc->bus_type & ASC_IS_PCI) && - (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) { - asc_dvc->bus_type = ASC_IS_PCI_ULTRA; - asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0; - asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1; - asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2; - asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3; - asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4; - asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5; - asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6; - asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7; - asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8; - asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9; - asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10; - asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11; - asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12; - asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13; - asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14; - asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15; - asc_dvc->max_sdtr_index = 15; - if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) - { - AscSetExtraControl(iop_base, - (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); - } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) { - AscSetExtraControl(iop_base, - (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER)); - } - } - if (asc_dvc->bus_type == ASC_IS_PCI) { - AscSetExtraControl(iop_base, (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); - } + int i; + PortAddr iop_base; + ushort warn_code; + uchar chip_version; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + asc_dvc->err_code = 0; + if ((asc_dvc->bus_type & + (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) { + asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE; + } + AscSetChipControl(iop_base, CC_HALT); + AscSetChipStatus(iop_base, 0); + asc_dvc->bug_fix_cntl = 0; + asc_dvc->pci_fix_asyn_xfer = 0; + asc_dvc->pci_fix_asyn_xfer_always = 0; + /* asc_dvc->init_state initalized in AscInitGetConfig(). */ + asc_dvc->sdtr_done = 0; + asc_dvc->cur_total_qng = 0; + asc_dvc->is_in_int = 0; + asc_dvc->in_critical_cnt = 0; + asc_dvc->last_q_shortage = 0; + asc_dvc->use_tagged_qng = 0; + asc_dvc->no_scam = 0; + asc_dvc->unit_not_ready = 0; + asc_dvc->queue_full_or_busy = 0; + asc_dvc->redo_scam = 0; + asc_dvc->res2 = 0; + asc_dvc->host_init_sdtr_index = 0; + asc_dvc->cfg->can_tagged_qng = 0; + asc_dvc->cfg->cmd_qng_enabled = 0; + asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; + asc_dvc->init_sdtr = 0; + asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; + asc_dvc->scsi_reset_wait = 3; + asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); + asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; + asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; + asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; + asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | + ASC_LIB_VERSION_MINOR; + chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type); + asc_dvc->cfg->chip_version = chip_version; + asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0; + asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1; + asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2; + asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3; + asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4; + asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5; + asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6; + asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7; + asc_dvc->max_sdtr_index = 7; + if ((asc_dvc->bus_type & ASC_IS_PCI) && + (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) { + asc_dvc->bus_type = ASC_IS_PCI_ULTRA; + asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0; + asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1; + asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2; + asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3; + asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4; + asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5; + asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6; + asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7; + asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8; + asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9; + asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10; + asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11; + asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12; + asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13; + asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14; + asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15; + asc_dvc->max_sdtr_index = 15; + if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) { + AscSetExtraControl(iop_base, + (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); + } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) { + AscSetExtraControl(iop_base, + (SEC_ACTIVE_NEGATE | + SEC_ENABLE_FILTER)); + } + } + if (asc_dvc->bus_type == ASC_IS_PCI) { + AscSetExtraControl(iop_base, + (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); + } - asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; - if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) { - AscSetChipIFC(iop_base, IFC_INIT_DEFAULT); - asc_dvc->bus_type = ASC_IS_ISAPNP; - } + asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; + if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) { + AscSetChipIFC(iop_base, IFC_INIT_DEFAULT); + asc_dvc->bus_type = ASC_IS_ISAPNP; + } #ifdef CONFIG_ISA - if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { - asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base); - } + if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { + asc_dvc->cfg->isa_dma_channel = + (uchar)AscGetIsaDmaChannel(iop_base); + } #endif /* CONFIG_ISA */ - for (i = 0; i <= ASC_MAX_TID; i++) { - asc_dvc->cur_dvc_qng[i] = 0; - asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG; - asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *) 0L; - asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *) 0L; - asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG; - } - return (warn_code); + for (i = 0; i <= ASC_MAX_TID; i++) { + asc_dvc->cur_dvc_qng[i] = 0; + asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG; + asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L; + asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L; + asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG; + } + return (warn_code); } -STATIC ushort __init -AscInitFromEEP(ASC_DVC_VAR *asc_dvc) +static ushort __init AscInitFromEEP(ASC_DVC_VAR *asc_dvc) { - ASCEEP_CONFIG eep_config_buf; - ASCEEP_CONFIG *eep_config; - PortAddr iop_base; - ushort chksum; - ushort warn_code; - ushort cfg_msw, cfg_lsw; - int i; - int write_eep = 0; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); - AscStopQueueExe(iop_base); - if ((AscStopChip(iop_base) == FALSE) || - (AscGetChipScsiCtrl(iop_base) != 0)) { - asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; - AscResetChipAndScsiBus(asc_dvc); - DvcSleepMilliSecond((ASC_DCNT) - ((ushort) asc_dvc->scsi_reset_wait * 1000)); - } - if (AscIsChipHalted(iop_base) == FALSE) { - asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; - return (warn_code); - } - AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); - if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { - asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; - return (warn_code); - } - eep_config = (ASCEEP_CONFIG *) &eep_config_buf; - cfg_msw = AscGetChipCfgMsw(iop_base); - cfg_lsw = AscGetChipCfgLsw(iop_base); - if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { - cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); - warn_code |= ASC_WARN_CFG_MSW_RECOVER; - AscSetChipCfgMsw(iop_base, cfg_msw); - } - chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); - ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum); - if (chksum == 0) { - chksum = 0xaa55; - } - if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { - warn_code |= ASC_WARN_AUTO_CONFIG; - if (asc_dvc->cfg->chip_version == 3) { - if (eep_config->cfg_lsw != cfg_lsw) { - warn_code |= ASC_WARN_EEPROM_RECOVER; - eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base); - } - if (eep_config->cfg_msw != cfg_msw) { - warn_code |= ASC_WARN_EEPROM_RECOVER; - eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); - } - } - } - eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; - eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; - ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n", - eep_config->chksum); - if (chksum != eep_config->chksum) { - if (AscGetChipVersion(iop_base, asc_dvc->bus_type) == - ASC_CHIP_VER_PCI_ULTRA_3050 ) - { - ASC_DBG(1, -"AscInitFromEEP: chksum error ignored; EEPROM-less board\n"); - eep_config->init_sdtr = 0xFF; - eep_config->disc_enable = 0xFF; - eep_config->start_motor = 0xFF; - eep_config->use_cmd_qng = 0; - eep_config->max_total_qng = 0xF0; - eep_config->max_tag_qng = 0x20; - eep_config->cntl = 0xBFFF; - ASC_EEP_SET_CHIP_ID(eep_config, 7); - eep_config->no_scam = 0; - eep_config->adapter_info[0] = 0; - eep_config->adapter_info[1] = 0; - eep_config->adapter_info[2] = 0; - eep_config->adapter_info[3] = 0; - eep_config->adapter_info[4] = 0; - /* Indicate EEPROM-less board. */ - eep_config->adapter_info[5] = 0xBB; - } else { - ASC_PRINT( -"AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n"); - write_eep = 1; - warn_code |= ASC_WARN_EEPROM_CHKSUM; - } - } - asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr; - asc_dvc->cfg->disc_enable = eep_config->disc_enable; - asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; - asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config); - asc_dvc->start_motor = eep_config->start_motor; - asc_dvc->dvc_cntl = eep_config->cntl; - asc_dvc->no_scam = eep_config->no_scam; - asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0]; - asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1]; - asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2]; - asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3]; - asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4]; - asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5]; - if (!AscTestExternalLram(asc_dvc)) { - if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) { - eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG; - eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG; - } else { - eep_config->cfg_msw |= 0x0800; - cfg_msw |= 0x0800; - AscSetChipCfgMsw(iop_base, cfg_msw); - eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; - eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; - } - } else { - } - if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { - eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; - } - if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { - eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; - } - if (eep_config->max_tag_qng > eep_config->max_total_qng) { - eep_config->max_tag_qng = eep_config->max_total_qng; - } - if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { - eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; - } - asc_dvc->max_total_qng = eep_config->max_total_qng; - if ((eep_config->use_cmd_qng & eep_config->disc_enable) != - eep_config->use_cmd_qng) { - eep_config->disc_enable = eep_config->use_cmd_qng; - warn_code |= ASC_WARN_CMD_QNG_CONFLICT; - } - if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { - asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); - } - ASC_EEP_SET_CHIP_ID(eep_config, ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID); - asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config); - if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) && - !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) { - asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX; - } + ASCEEP_CONFIG eep_config_buf; + ASCEEP_CONFIG *eep_config; + PortAddr iop_base; + ushort chksum; + ushort warn_code; + ushort cfg_msw, cfg_lsw; + int i; + int write_eep = 0; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); + AscStopQueueExe(iop_base); + if ((AscStopChip(iop_base) == FALSE) || + (AscGetChipScsiCtrl(iop_base) != 0)) { + asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; + AscResetChipAndScsiBus(asc_dvc); + DvcSleepMilliSecond((ASC_DCNT) + ((ushort)asc_dvc->scsi_reset_wait * 1000)); + } + if (AscIsChipHalted(iop_base) == FALSE) { + asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; + return (warn_code); + } + AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); + if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { + asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; + return (warn_code); + } + eep_config = (ASCEEP_CONFIG *)&eep_config_buf; + cfg_msw = AscGetChipCfgMsw(iop_base); + cfg_lsw = AscGetChipCfgLsw(iop_base); + if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { + cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); + warn_code |= ASC_WARN_CFG_MSW_RECOVER; + AscSetChipCfgMsw(iop_base, cfg_msw); + } + chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); + ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum); + if (chksum == 0) { + chksum = 0xaa55; + } + if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { + warn_code |= ASC_WARN_AUTO_CONFIG; + if (asc_dvc->cfg->chip_version == 3) { + if (eep_config->cfg_lsw != cfg_lsw) { + warn_code |= ASC_WARN_EEPROM_RECOVER; + eep_config->cfg_lsw = + AscGetChipCfgLsw(iop_base); + } + if (eep_config->cfg_msw != cfg_msw) { + warn_code |= ASC_WARN_EEPROM_RECOVER; + eep_config->cfg_msw = + AscGetChipCfgMsw(iop_base); + } + } + } + eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; + eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; + ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n", + eep_config->chksum); + if (chksum != eep_config->chksum) { + if (AscGetChipVersion(iop_base, asc_dvc->bus_type) == + ASC_CHIP_VER_PCI_ULTRA_3050) { + ASC_DBG(1, + "AscInitFromEEP: chksum error ignored; EEPROM-less board\n"); + eep_config->init_sdtr = 0xFF; + eep_config->disc_enable = 0xFF; + eep_config->start_motor = 0xFF; + eep_config->use_cmd_qng = 0; + eep_config->max_total_qng = 0xF0; + eep_config->max_tag_qng = 0x20; + eep_config->cntl = 0xBFFF; + ASC_EEP_SET_CHIP_ID(eep_config, 7); + eep_config->no_scam = 0; + eep_config->adapter_info[0] = 0; + eep_config->adapter_info[1] = 0; + eep_config->adapter_info[2] = 0; + eep_config->adapter_info[3] = 0; + eep_config->adapter_info[4] = 0; + /* Indicate EEPROM-less board. */ + eep_config->adapter_info[5] = 0xBB; + } else { + ASC_PRINT + ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n"); + write_eep = 1; + warn_code |= ASC_WARN_EEPROM_CHKSUM; + } + } + asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr; + asc_dvc->cfg->disc_enable = eep_config->disc_enable; + asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; + asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config); + asc_dvc->start_motor = eep_config->start_motor; + asc_dvc->dvc_cntl = eep_config->cntl; + asc_dvc->no_scam = eep_config->no_scam; + asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0]; + asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1]; + asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2]; + asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3]; + asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4]; + asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5]; + if (!AscTestExternalLram(asc_dvc)) { + if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == + ASC_IS_PCI_ULTRA)) { + eep_config->max_total_qng = + ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG; + eep_config->max_tag_qng = + ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG; + } else { + eep_config->cfg_msw |= 0x0800; + cfg_msw |= 0x0800; + AscSetChipCfgMsw(iop_base, cfg_msw); + eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; + eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; + } + } else { + } + if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { + eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; + } + if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { + eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; + } + if (eep_config->max_tag_qng > eep_config->max_total_qng) { + eep_config->max_tag_qng = eep_config->max_total_qng; + } + if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { + eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; + } + asc_dvc->max_total_qng = eep_config->max_total_qng; + if ((eep_config->use_cmd_qng & eep_config->disc_enable) != + eep_config->use_cmd_qng) { + eep_config->disc_enable = eep_config->use_cmd_qng; + warn_code |= ASC_WARN_CMD_QNG_CONFLICT; + } + if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { + asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); + } + ASC_EEP_SET_CHIP_ID(eep_config, + ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID); + asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config); + if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) && + !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) { + asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX; + } - for (i = 0; i <= ASC_MAX_TID; i++) { - asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i]; - asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; - asc_dvc->cfg->sdtr_period_offset[i] = - (uchar) (ASC_DEF_SDTR_OFFSET | - (asc_dvc->host_init_sdtr_index << 4)); - } - eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); - if (write_eep) { - if ((i = AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type)) != - 0) { - ASC_PRINT1( -"AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", i); - } else { - ASC_PRINT("AscInitFromEEP: Successfully re-wrote EEPROM.\n"); - } - } - return (warn_code); + for (i = 0; i <= ASC_MAX_TID; i++) { + asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i]; + asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; + asc_dvc->cfg->sdtr_period_offset[i] = + (uchar)(ASC_DEF_SDTR_OFFSET | + (asc_dvc->host_init_sdtr_index << 4)); + } + eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); + if (write_eep) { + if ((i = + AscSetEEPConfig(iop_base, eep_config, + asc_dvc->bus_type)) != 0) { + ASC_PRINT1 + ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", + i); + } else { + ASC_PRINT + ("AscInitFromEEP: Successfully re-wrote EEPROM.\n"); + } + } + return (warn_code); } -STATIC ushort -AscInitMicroCodeVar( - ASC_DVC_VAR *asc_dvc -) +static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc) { - int i; - ushort warn_code; - PortAddr iop_base; - ASC_PADDR phy_addr; - ASC_DCNT phy_size; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - for (i = 0; i <= ASC_MAX_TID; i++) { - AscPutMCodeInitSDTRAtID(iop_base, i, - asc_dvc->cfg->sdtr_period_offset[i] -); - } + int i; + ushort warn_code; + PortAddr iop_base; + ASC_PADDR phy_addr; + ASC_DCNT phy_size; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + for (i = 0; i <= ASC_MAX_TID; i++) { + AscPutMCodeInitSDTRAtID(iop_base, i, + asc_dvc->cfg->sdtr_period_offset[i] + ); + } - AscInitQLinkVar(asc_dvc); - AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, - asc_dvc->cfg->disc_enable); - AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, - ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); - - /* Align overrun buffer on an 8 byte boundary. */ - phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf); - phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7); - AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, - (uchar *) &phy_addr, 1); - phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8); - AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D, - (uchar *) &phy_size, 1); - - asc_dvc->cfg->mcode_date = - AscReadLramWord(iop_base, (ushort) ASCV_MC_DATE_W); - asc_dvc->cfg->mcode_version = - AscReadLramWord(iop_base, (ushort) ASCV_MC_VER_W); - - AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); - if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { - asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; - return (warn_code); - } - if (AscStartChip(iop_base) != 1) { - asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; - return (warn_code); - } + AscInitQLinkVar(asc_dvc); + AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, + asc_dvc->cfg->disc_enable); + AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, + ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); + + /* Align overrun buffer on an 8 byte boundary. */ + phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf); + phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7); + AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, + (uchar *)&phy_addr, 1); + phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8); + AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D, + (uchar *)&phy_size, 1); + + asc_dvc->cfg->mcode_date = + AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W); + asc_dvc->cfg->mcode_version = + AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W); + + AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); + if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { + asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; + return (warn_code); + } + if (AscStartChip(iop_base) != 1) { + asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; + return (warn_code); + } - return (warn_code); + return (warn_code); } -STATIC int __init -AscTestExternalLram( - ASC_DVC_VAR *asc_dvc) +static int __init AscTestExternalLram(ASC_DVC_VAR *asc_dvc) { - PortAddr iop_base; - ushort q_addr; - ushort saved_word; - int sta; - - iop_base = asc_dvc->iop_base; - sta = 0; - q_addr = ASC_QNO_TO_QADDR(241); - saved_word = AscReadLramWord(iop_base, q_addr); - AscSetChipLramAddr(iop_base, q_addr); - AscSetChipLramData(iop_base, 0x55AA); - DvcSleepMilliSecond(10); - AscSetChipLramAddr(iop_base, q_addr); - if (AscGetChipLramData(iop_base) == 0x55AA) { - sta = 1; - AscWriteLramWord(iop_base, q_addr, saved_word); - } - return (sta); + PortAddr iop_base; + ushort q_addr; + ushort saved_word; + int sta; + + iop_base = asc_dvc->iop_base; + sta = 0; + q_addr = ASC_QNO_TO_QADDR(241); + saved_word = AscReadLramWord(iop_base, q_addr); + AscSetChipLramAddr(iop_base, q_addr); + AscSetChipLramData(iop_base, 0x55AA); + DvcSleepMilliSecond(10); + AscSetChipLramAddr(iop_base, q_addr); + if (AscGetChipLramData(iop_base) == 0x55AA) { + sta = 1; + AscWriteLramWord(iop_base, q_addr, saved_word); + } + return (sta); } -STATIC int __init -AscWriteEEPCmdReg( - PortAddr iop_base, - uchar cmd_reg -) +static int __init AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg) { - uchar read_back; - int retry; - - retry = 0; - while (TRUE) { - AscSetChipEEPCmd(iop_base, cmd_reg); - DvcSleepMilliSecond(1); - read_back = AscGetChipEEPCmd(iop_base); - if (read_back == cmd_reg) { - return (1); - } - if (retry++ > ASC_EEP_MAX_RETRY) { - return (0); - } - } + uchar read_back; + int retry; + + retry = 0; + while (TRUE) { + AscSetChipEEPCmd(iop_base, cmd_reg); + DvcSleepMilliSecond(1); + read_back = AscGetChipEEPCmd(iop_base); + if (read_back == cmd_reg) { + return (1); + } + if (retry++ > ASC_EEP_MAX_RETRY) { + return (0); + } + } } -STATIC int __init -AscWriteEEPDataReg( - PortAddr iop_base, - ushort data_reg -) +static int __init AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) { - ushort read_back; - int retry; - - retry = 0; - while (TRUE) { - AscSetChipEEPData(iop_base, data_reg); - DvcSleepMilliSecond(1); - read_back = AscGetChipEEPData(iop_base); - if (read_back == data_reg) { - return (1); - } - if (retry++ > ASC_EEP_MAX_RETRY) { - return (0); - } - } + ushort read_back; + int retry; + + retry = 0; + while (TRUE) { + AscSetChipEEPData(iop_base, data_reg); + DvcSleepMilliSecond(1); + read_back = AscGetChipEEPData(iop_base); + if (read_back == data_reg) { + return (1); + } + if (retry++ > ASC_EEP_MAX_RETRY) { + return (0); + } + } } -STATIC void __init -AscWaitEEPRead(void) +static void __init AscWaitEEPRead(void) { - DvcSleepMilliSecond(1); - return; + DvcSleepMilliSecond(1); + return; } -STATIC void __init -AscWaitEEPWrite(void) +static void __init AscWaitEEPWrite(void) { - DvcSleepMilliSecond(20); - return; + DvcSleepMilliSecond(20); + return; } -STATIC ushort __init -AscReadEEPWord( - PortAddr iop_base, - uchar addr) +static ushort __init AscReadEEPWord(PortAddr iop_base, uchar addr) { - ushort read_wval; - uchar cmd_reg; - - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); - AscWaitEEPRead(); - cmd_reg = addr | ASC_EEP_CMD_READ; - AscWriteEEPCmdReg(iop_base, cmd_reg); - AscWaitEEPRead(); - read_wval = AscGetChipEEPData(iop_base); - AscWaitEEPRead(); - return (read_wval); + ushort read_wval; + uchar cmd_reg; + + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); + AscWaitEEPRead(); + cmd_reg = addr | ASC_EEP_CMD_READ; + AscWriteEEPCmdReg(iop_base, cmd_reg); + AscWaitEEPRead(); + read_wval = AscGetChipEEPData(iop_base); + AscWaitEEPRead(); + return (read_wval); } -STATIC ushort __init -AscWriteEEPWord( - PortAddr iop_base, - uchar addr, - ushort word_val) +static ushort __init +AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val) { - ushort read_wval; - - read_wval = AscReadEEPWord(iop_base, addr); - if (read_wval != word_val) { - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE); - AscWaitEEPRead(); - AscWriteEEPDataReg(iop_base, word_val); - AscWaitEEPRead(); - AscWriteEEPCmdReg(iop_base, - (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr)); - AscWaitEEPWrite(); - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); - AscWaitEEPRead(); - return (AscReadEEPWord(iop_base, addr)); - } - return (read_wval); + ushort read_wval; + + read_wval = AscReadEEPWord(iop_base, addr); + if (read_wval != word_val) { + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE); + AscWaitEEPRead(); + AscWriteEEPDataReg(iop_base, word_val); + AscWaitEEPRead(); + AscWriteEEPCmdReg(iop_base, + (uchar)((uchar)ASC_EEP_CMD_WRITE | addr)); + AscWaitEEPWrite(); + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); + AscWaitEEPRead(); + return (AscReadEEPWord(iop_base, addr)); + } + return (read_wval); } -STATIC ushort __init -AscGetEEPConfig( - PortAddr iop_base, - ASCEEP_CONFIG * cfg_buf, ushort bus_type) +static ushort __init +AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { - ushort wval; - ushort sum; - ushort *wbuf; - int cfg_beg; - int cfg_end; - int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; - int s_addr; - - wbuf = (ushort *) cfg_buf; - sum = 0; - /* Read two config words; Byte-swapping done by AscReadEEPWord(). */ - for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { - *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr); - sum += *wbuf; - } - if (bus_type & ASC_IS_VL) { - cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; - cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; - } else { - cfg_beg = ASC_EEP_DVC_CFG_BEG; - cfg_end = ASC_EEP_MAX_DVC_ADDR; - } - for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { - wval = AscReadEEPWord( iop_base, ( uchar )s_addr ) ; - if (s_addr <= uchar_end_in_config) { - /* - * Swap all char fields - must unswap bytes already swapped - * by AscReadEEPWord(). - */ - *wbuf = le16_to_cpu(wval); - } else { - /* Don't swap word field at the end - cntl field. */ - *wbuf = wval; - } - sum += wval; /* Checksum treats all EEPROM data as words. */ - } - /* - * Read the checksum word which will be compared against 'sum' - * by the caller. Word field already swapped. - */ - *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr); - return (sum); + ushort wval; + ushort sum; + ushort *wbuf; + int cfg_beg; + int cfg_end; + int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; + int s_addr; + + wbuf = (ushort *)cfg_buf; + sum = 0; + /* Read two config words; Byte-swapping done by AscReadEEPWord(). */ + for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { + *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); + sum += *wbuf; + } + if (bus_type & ASC_IS_VL) { + cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; + cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; + } else { + cfg_beg = ASC_EEP_DVC_CFG_BEG; + cfg_end = ASC_EEP_MAX_DVC_ADDR; + } + for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { + wval = AscReadEEPWord(iop_base, (uchar)s_addr); + if (s_addr <= uchar_end_in_config) { + /* + * Swap all char fields - must unswap bytes already swapped + * by AscReadEEPWord(). + */ + *wbuf = le16_to_cpu(wval); + } else { + /* Don't swap word field at the end - cntl field. */ + *wbuf = wval; + } + sum += wval; /* Checksum treats all EEPROM data as words. */ + } + /* + * Read the checksum word which will be compared against 'sum' + * by the caller. Word field already swapped. + */ + *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); + return (sum); } -STATIC int __init -AscSetEEPConfigOnce( - PortAddr iop_base, - ASCEEP_CONFIG * cfg_buf, ushort bus_type) +static int __init +AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { - int n_error; - ushort *wbuf; - ushort word; - ushort sum; - int s_addr; - int cfg_beg; - int cfg_end; - int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; - - - wbuf = (ushort *) cfg_buf; - n_error = 0; - sum = 0; - /* Write two config words; AscWriteEEPWord() will swap bytes. */ - for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { - sum += *wbuf; - if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { - n_error++; - } - } - if (bus_type & ASC_IS_VL) { - cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; - cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; - } else { - cfg_beg = ASC_EEP_DVC_CFG_BEG; - cfg_end = ASC_EEP_MAX_DVC_ADDR; - } - for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { - if (s_addr <= uchar_end_in_config) { - /* - * This is a char field. Swap char fields before they are - * swapped again by AscWriteEEPWord(). - */ - word = cpu_to_le16(*wbuf); - if (word != AscWriteEEPWord( iop_base, (uchar) s_addr, word)) { - n_error++; - } - } else { - /* Don't swap word field at the end - cntl field. */ - if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { - n_error++; - } - } - sum += *wbuf; /* Checksum calculated from word values. */ - } - /* Write checksum word. It will be swapped by AscWriteEEPWord(). */ - *wbuf = sum; - if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) { - n_error++; - } + int n_error; + ushort *wbuf; + ushort word; + ushort sum; + int s_addr; + int cfg_beg; + int cfg_end; + int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; + + wbuf = (ushort *)cfg_buf; + n_error = 0; + sum = 0; + /* Write two config words; AscWriteEEPWord() will swap bytes. */ + for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { + sum += *wbuf; + if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) { + n_error++; + } + } + if (bus_type & ASC_IS_VL) { + cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; + cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; + } else { + cfg_beg = ASC_EEP_DVC_CFG_BEG; + cfg_end = ASC_EEP_MAX_DVC_ADDR; + } + for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { + if (s_addr <= uchar_end_in_config) { + /* + * This is a char field. Swap char fields before they are + * swapped again by AscWriteEEPWord(). + */ + word = cpu_to_le16(*wbuf); + if (word != + AscWriteEEPWord(iop_base, (uchar)s_addr, word)) { + n_error++; + } + } else { + /* Don't swap word field at the end - cntl field. */ + if (*wbuf != + AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) { + n_error++; + } + } + sum += *wbuf; /* Checksum calculated from word values. */ + } + /* Write checksum word. It will be swapped by AscWriteEEPWord(). */ + *wbuf = sum; + if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) { + n_error++; + } - /* Read EEPROM back again. */ - wbuf = (ushort *) cfg_buf; - /* - * Read two config words; Byte-swapping done by AscReadEEPWord(). - */ - for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { - if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) { - n_error++; - } - } - if (bus_type & ASC_IS_VL) { - cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; - cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; - } else { - cfg_beg = ASC_EEP_DVC_CFG_BEG; - cfg_end = ASC_EEP_MAX_DVC_ADDR; - } - for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { - if (s_addr <= uchar_end_in_config) { - /* - * Swap all char fields. Must unswap bytes already swapped - * by AscReadEEPWord(). - */ - word = le16_to_cpu(AscReadEEPWord(iop_base, (uchar) s_addr)); - } else { - /* Don't swap word field at the end - cntl field. */ - word = AscReadEEPWord(iop_base, (uchar) s_addr); - } - if (*wbuf != word) { - n_error++; - } - } - /* Read checksum; Byte swapping not needed. */ - if (AscReadEEPWord(iop_base, (uchar) s_addr) != sum) { - n_error++; - } - return (n_error); + /* Read EEPROM back again. */ + wbuf = (ushort *)cfg_buf; + /* + * Read two config words; Byte-swapping done by AscReadEEPWord(). + */ + for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { + if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) { + n_error++; + } + } + if (bus_type & ASC_IS_VL) { + cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; + cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; + } else { + cfg_beg = ASC_EEP_DVC_CFG_BEG; + cfg_end = ASC_EEP_MAX_DVC_ADDR; + } + for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { + if (s_addr <= uchar_end_in_config) { + /* + * Swap all char fields. Must unswap bytes already swapped + * by AscReadEEPWord(). + */ + word = + le16_to_cpu(AscReadEEPWord + (iop_base, (uchar)s_addr)); + } else { + /* Don't swap word field at the end - cntl field. */ + word = AscReadEEPWord(iop_base, (uchar)s_addr); + } + if (*wbuf != word) { + n_error++; + } + } + /* Read checksum; Byte swapping not needed. */ + if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) { + n_error++; + } + return (n_error); } -STATIC int __init -AscSetEEPConfig( - PortAddr iop_base, - ASCEEP_CONFIG * cfg_buf, ushort bus_type -) +static int __init +AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { - int retry; - int n_error; - - retry = 0; - while (TRUE) { - if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf, - bus_type)) == 0) { - break; - } - if (++retry > ASC_EEP_MAX_RETRY) { - break; - } - } - return (n_error); + int retry; + int n_error; + + retry = 0; + while (TRUE) { + if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf, + bus_type)) == 0) { + break; + } + if (++retry > ASC_EEP_MAX_RETRY) { + break; + } + } + return (n_error); } -STATIC void -AscAsyncFix( - ASC_DVC_VAR *asc_dvc, - uchar tid_no, - ASC_SCSI_INQUIRY *inq) +static void +AscAsyncFix(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq) { - uchar dvc_type; - ASC_SCSI_BIT_ID_TYPE tid_bits; - - dvc_type = ASC_INQ_DVC_TYPE(inq); - tid_bits = ASC_TIX_TO_TARGET_ID(tid_no); - - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) - { - if (!(asc_dvc->init_sdtr & tid_bits)) - { - if ((dvc_type == TYPE_ROM) && - (AscCompareString((uchar *) inq->vendor_id, - (uchar *) "HP ", 3) == 0)) - { - asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; - } - asc_dvc->pci_fix_asyn_xfer |= tid_bits; - if ((dvc_type == TYPE_PROCESSOR) || - (dvc_type == TYPE_SCANNER) || - (dvc_type == TYPE_ROM) || - (dvc_type == TYPE_TAPE)) - { - asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; - } - - if (asc_dvc->pci_fix_asyn_xfer & tid_bits) - { - AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no, - ASYN_SDTR_DATA_FIX_PCI_REV_AB); - } - } - } - return; + uchar dvc_type; + ASC_SCSI_BIT_ID_TYPE tid_bits; + + dvc_type = ASC_INQ_DVC_TYPE(inq); + tid_bits = ASC_TIX_TO_TARGET_ID(tid_no); + + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) { + if (!(asc_dvc->init_sdtr & tid_bits)) { + if ((dvc_type == TYPE_ROM) && + (AscCompareString((uchar *)inq->vendor_id, + (uchar *)"HP ", 3) == 0)) { + asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; + } + asc_dvc->pci_fix_asyn_xfer |= tid_bits; + if ((dvc_type == TYPE_PROCESSOR) || + (dvc_type == TYPE_SCANNER) || + (dvc_type == TYPE_ROM) || (dvc_type == TYPE_TAPE)) { + asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; + } + + if (asc_dvc->pci_fix_asyn_xfer & tid_bits) { + AscSetRunChipSynRegAtID(asc_dvc->iop_base, + tid_no, + ASYN_SDTR_DATA_FIX_PCI_REV_AB); + } + } + } + return; } -STATIC int -AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq) +static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq) { - if ((inq->add_len >= 32) && - (AscCompareString((uchar *) inq->vendor_id, - (uchar *) "QUANTUM XP34301", 15) == 0) && - (AscCompareString((uchar *) inq->product_rev_level, - (uchar *) "1071", 4) == 0)) - { - return 0; - } - return 1; + if ((inq->add_len >= 32) && + (AscCompareString((uchar *)inq->vendor_id, + (uchar *)"QUANTUM XP34301", 15) == 0) && + (AscCompareString((uchar *)inq->product_rev_level, + (uchar *)"1071", 4) == 0)) { + return 0; + } + return 1; } -STATIC void -AscInquiryHandling(ASC_DVC_VAR *asc_dvc, - uchar tid_no, ASC_SCSI_INQUIRY *inq) +static void +AscInquiryHandling(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq) { - ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no); - ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng; - - orig_init_sdtr = asc_dvc->init_sdtr; - orig_use_tagged_qng = asc_dvc->use_tagged_qng; - - asc_dvc->init_sdtr &= ~tid_bit; - asc_dvc->cfg->can_tagged_qng &= ~tid_bit; - asc_dvc->use_tagged_qng &= ~tid_bit; - - if (ASC_INQ_RESPONSE_FMT(inq) >= 2 || ASC_INQ_ANSI_VER(inq) >= 2) { - if ((asc_dvc->cfg->sdtr_enable & tid_bit) && ASC_INQ_SYNC(inq)) { - asc_dvc->init_sdtr |= tid_bit; - } - if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && - ASC_INQ_CMD_QUEUE(inq)) { - if (AscTagQueuingSafe(inq)) { - asc_dvc->use_tagged_qng |= tid_bit; - asc_dvc->cfg->can_tagged_qng |= tid_bit; - } - } - } - if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) { - AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, - asc_dvc->cfg->disc_enable); - AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, - asc_dvc->use_tagged_qng); - AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, - asc_dvc->cfg->can_tagged_qng); - - asc_dvc->max_dvc_qng[tid_no] = - asc_dvc->cfg->max_tag_qng[tid_no]; - AscWriteLramByte(asc_dvc->iop_base, - (ushort) (ASCV_MAX_DVC_QNG_BEG + tid_no), - asc_dvc->max_dvc_qng[tid_no]); - } - if (orig_init_sdtr != asc_dvc->init_sdtr) { - AscAsyncFix(asc_dvc, tid_no, inq); - } - return; + ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no); + ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng; + + orig_init_sdtr = asc_dvc->init_sdtr; + orig_use_tagged_qng = asc_dvc->use_tagged_qng; + + asc_dvc->init_sdtr &= ~tid_bit; + asc_dvc->cfg->can_tagged_qng &= ~tid_bit; + asc_dvc->use_tagged_qng &= ~tid_bit; + + if (ASC_INQ_RESPONSE_FMT(inq) >= 2 || ASC_INQ_ANSI_VER(inq) >= 2) { + if ((asc_dvc->cfg->sdtr_enable & tid_bit) && ASC_INQ_SYNC(inq)) { + asc_dvc->init_sdtr |= tid_bit; + } + if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && + ASC_INQ_CMD_QUEUE(inq)) { + if (AscTagQueuingSafe(inq)) { + asc_dvc->use_tagged_qng |= tid_bit; + asc_dvc->cfg->can_tagged_qng |= tid_bit; + } + } + } + if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) { + AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, + asc_dvc->cfg->disc_enable); + AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, + asc_dvc->use_tagged_qng); + AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, + asc_dvc->cfg->can_tagged_qng); + + asc_dvc->max_dvc_qng[tid_no] = + asc_dvc->cfg->max_tag_qng[tid_no]; + AscWriteLramByte(asc_dvc->iop_base, + (ushort)(ASCV_MAX_DVC_QNG_BEG + tid_no), + asc_dvc->max_dvc_qng[tid_no]); + } + if (orig_init_sdtr != asc_dvc->init_sdtr) { + AscAsyncFix(asc_dvc, tid_no, inq); + } + return; } -STATIC int -AscCompareString( - uchar *str1, - uchar *str2, - int len -) +static int AscCompareString(uchar *str1, uchar *str2, int len) { - int i; - int diff; + int i; + int diff; - for (i = 0; i < len; i++) { - diff = (int) (str1[i] - str2[i]); - if (diff != 0) - return (diff); - } - return (0); + for (i = 0; i < len; i++) { + diff = (int)(str1[i] - str2[i]); + if (diff != 0) + return (diff); + } + return (0); } -STATIC uchar -AscReadLramByte( - PortAddr iop_base, - ushort addr -) +static uchar AscReadLramByte(PortAddr iop_base, ushort addr) { - uchar byte_data; - ushort word_data; - - if (isodd_word(addr)) { - AscSetChipLramAddr(iop_base, addr - 1); - word_data = AscGetChipLramData(iop_base); - byte_data = (uchar) ((word_data >> 8) & 0xFF); - } else { - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - byte_data = (uchar) (word_data & 0xFF); - } - return (byte_data); + uchar byte_data; + ushort word_data; + + if (isodd_word(addr)) { + AscSetChipLramAddr(iop_base, addr - 1); + word_data = AscGetChipLramData(iop_base); + byte_data = (uchar)((word_data >> 8) & 0xFF); + } else { + AscSetChipLramAddr(iop_base, addr); + word_data = AscGetChipLramData(iop_base); + byte_data = (uchar)(word_data & 0xFF); + } + return (byte_data); } -STATIC ushort -AscReadLramWord( - PortAddr iop_base, - ushort addr -) + +static ushort AscReadLramWord(PortAddr iop_base, ushort addr) { - ushort word_data; + ushort word_data; - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - return (word_data); + AscSetChipLramAddr(iop_base, addr); + word_data = AscGetChipLramData(iop_base); + return (word_data); } #if CC_VERY_LONG_SG_LIST -STATIC ASC_DCNT -AscReadLramDWord( - PortAddr iop_base, - ushort addr -) +static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr) { - ushort val_low, val_high; - ASC_DCNT dword_data; - - AscSetChipLramAddr(iop_base, addr); - val_low = AscGetChipLramData(iop_base); - val_high = AscGetChipLramData(iop_base); - dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low; - return (dword_data); + ushort val_low, val_high; + ASC_DCNT dword_data; + + AscSetChipLramAddr(iop_base, addr); + val_low = AscGetChipLramData(iop_base); + val_high = AscGetChipLramData(iop_base); + dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low; + return (dword_data); } #endif /* CC_VERY_LONG_SG_LIST */ -STATIC void -AscWriteLramWord( - PortAddr iop_base, - ushort addr, - ushort word_val -) +static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val) { - AscSetChipLramAddr(iop_base, addr); - AscSetChipLramData(iop_base, word_val); - return; + AscSetChipLramAddr(iop_base, addr); + AscSetChipLramData(iop_base, word_val); + return; } -STATIC void -AscWriteLramByte( - PortAddr iop_base, - ushort addr, - uchar byte_val -) +static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val) { - ushort word_data; - - if (isodd_word(addr)) { - addr--; - word_data = AscReadLramWord(iop_base, addr); - word_data &= 0x00FF; - word_data |= (((ushort) byte_val << 8) & 0xFF00); - } else { - word_data = AscReadLramWord(iop_base, addr); - word_data &= 0xFF00; - word_data |= ((ushort) byte_val & 0x00FF); - } - AscWriteLramWord(iop_base, addr, word_data); - return; + ushort word_data; + + if (isodd_word(addr)) { + addr--; + word_data = AscReadLramWord(iop_base, addr); + word_data &= 0x00FF; + word_data |= (((ushort)byte_val << 8) & 0xFF00); + } else { + word_data = AscReadLramWord(iop_base, addr); + word_data &= 0xFF00; + word_data |= ((ushort)byte_val & 0x00FF); + } + AscWriteLramWord(iop_base, addr, word_data); + return; } /* @@ -12841,30 +11628,26 @@ AscWriteLramByte( * The source data is assumed to be in little-endian order in memory * and is maintained in little-endian order when written to LRAM. */ -STATIC void -AscMemWordCopyPtrToLram( - PortAddr iop_base, - ushort s_addr, - uchar *s_buffer, - int words -) +static void +AscMemWordCopyPtrToLram(PortAddr iop_base, + ushort s_addr, uchar *s_buffer, int words) { - int i; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - /* - * On a little-endian system the second argument below - * produces a little-endian ushort which is written to - * LRAM in little-endian order. On a big-endian system - * the second argument produces a big-endian ushort which - * is "transparently" byte-swapped by outpw() and written - * in little-endian order to LRAM. - */ - outpw(iop_base + IOP_RAM_DATA, - ((ushort) s_buffer[i + 1] << 8) | s_buffer[i]); - } - return; + int i; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + /* + * On a little-endian system the second argument below + * produces a little-endian ushort which is written to + * LRAM in little-endian order. On a big-endian system + * the second argument produces a big-endian ushort which + * is "transparently" byte-swapped by outpw() and written + * in little-endian order to LRAM. + */ + outpw(iop_base + IOP_RAM_DATA, + ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); + } + return; } /* @@ -12873,24 +11656,18 @@ AscMemWordCopyPtrToLram( * The source data is assumed to be in little-endian order in memory * and is maintained in little-endian order when writen to LRAM. */ -STATIC void -AscMemDWordCopyPtrToLram( - PortAddr iop_base, - ushort s_addr, - uchar *s_buffer, - int dwords -) +static void +AscMemDWordCopyPtrToLram(PortAddr iop_base, + ushort s_addr, uchar *s_buffer, int dwords) { - int i; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 4 * dwords; i += 4) { - outpw(iop_base + IOP_RAM_DATA, - ((ushort) s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */ - outpw(iop_base + IOP_RAM_DATA, - ((ushort) s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */ - } - return; + int i; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 4 * dwords; i += 4) { + outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */ + outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */ + } + return; } /* @@ -12899,61 +11676,46 @@ AscMemDWordCopyPtrToLram( * The source data is assumed to be in little-endian order in LRAM * and is maintained in little-endian order when written to memory. */ -STATIC void -AscMemWordCopyPtrFromLram( - PortAddr iop_base, - ushort s_addr, - uchar *d_buffer, - int words -) +static void +AscMemWordCopyPtrFromLram(PortAddr iop_base, + ushort s_addr, uchar *d_buffer, int words) { - int i; - ushort word; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - word = inpw(iop_base + IOP_RAM_DATA); - d_buffer[i] = word & 0xff; - d_buffer[i + 1] = (word >> 8) & 0xff; - } - return; + int i; + ushort word; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + word = inpw(iop_base + IOP_RAM_DATA); + d_buffer[i] = word & 0xff; + d_buffer[i + 1] = (word >> 8) & 0xff; + } + return; } -STATIC ASC_DCNT -AscMemSumLramWord( - PortAddr iop_base, - ushort s_addr, - int words -) +static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words) { - ASC_DCNT sum; - int i; + ASC_DCNT sum; + int i; - sum = 0L; - for (i = 0; i < words; i++, s_addr += 2) { - sum += AscReadLramWord(iop_base, s_addr); - } - return (sum); + sum = 0L; + for (i = 0; i < words; i++, s_addr += 2) { + sum += AscReadLramWord(iop_base, s_addr); + } + return (sum); } -STATIC void -AscMemWordSetLram( - PortAddr iop_base, - ushort s_addr, - ushort set_wval, - int words -) +static void +AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words) { - int i; + int i; - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < words; i++) { - AscSetChipLramData(iop_base, set_wval); - } - return; + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < words; i++) { + AscSetChipLramData(iop_base, set_wval); + } + return; } - /* * --- Adv Library Functions */ @@ -12961,1076 +11723,2112 @@ AscMemWordSetLram( /* a_mcode.h */ /* Microcode buffer is kept after initialization for error recovery. */ -STATIC unsigned char _adv_asc3550_buf[] = { - 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc, 0x01, 0x00, 0x48, 0xe4, - 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, - 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6, - 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00, 0x00, 0xec, 0x85, 0xf0, - 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54, 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, - 0x98, 0x57, 0xd0, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80, - 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, - 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, - 0xc0, 0x00, 0x01, 0x01, 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54, - 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00, 0x3e, 0x00, 0x80, 0x00, - 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, - 0x78, 0x01, 0x62, 0x0a, 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55, - 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0, 0x03, 0xf7, 0x06, 0xf7, - 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00, 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, - 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0, - 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, - 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10, 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, - 0x00, 0x4e, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0, - 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, - 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, - 0x04, 0x10, 0x0a, 0x10, 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15, - 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, - 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, - 0x0b, 0xf0, 0x0c, 0xf0, 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, - 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x9e, 0x00, 0xa8, 0x00, - 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, - 0xc2, 0x01, 0x7c, 0x02, 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08, - 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x06, 0x12, - 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13, 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, - 0xd2, 0x17, 0x6b, 0x18, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47, - 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55, 0x14, 0x56, 0x77, 0x57, - 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90, 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, - 0xb8, 0x0c, 0xff, 0x10, 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff, - 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, 0x00, 0xfe, 0x57, 0x24, - 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00, 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, - 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f, - 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, 0xfe, 0x04, 0xf7, 0xcf, - 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe, 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, - 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, - 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b, 0x02, 0xfe, 0xd4, 0x0c, - 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, - 0x00, 0xfe, 0xd3, 0x12, 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02, - 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02, 0xfe, 0x46, 0xf0, 0xfe, - 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, - 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18, - 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, - 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, - 0x02, 0x29, 0x14, 0x4d, 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd, - 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, 0x58, 0x1c, 0x17, 0x06, - 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, - 0x5a, 0x1c, 0xea, 0xfe, 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f, - 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe, 0x69, 0x10, 0x17, 0x06, - 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d, 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, - 0x52, 0x16, 0x09, 0x4a, 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40, - 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0x99, 0x01, - 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03, 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, - 0xe8, 0x27, 0xf8, 0xfe, 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b, - 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0, 0xfe, 0x56, 0x03, 0xfe, - 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0, 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, - 0x64, 0x03, 0xeb, 0x0f, 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04, - 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40, 0x01, 0x0e, 0xac, 0x75, - 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2, 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, - 0x92, 0x03, 0xec, 0x11, 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4, - 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe, 0x0a, 0xf0, 0xfe, 0x7a, - 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe, 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, - 0x66, 0x02, 0x02, 0xd1, 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c, - 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3, 0x0a, 0xca, 0x01, 0x0e, - 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28, 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, - 0xfe, 0x66, 0x02, 0x02, 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f, - 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2b, 0xff, 0x02, - 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04, 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, - 0xfe, 0x4c, 0x44, 0xfe, 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64, - 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d, 0xfe, 0x2a, 0x13, 0x2f, - 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, - 0x09, 0x04, 0x1d, 0xfe, 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12, - 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, - 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, - 0xfe, 0x42, 0x5b, 0x67, 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, - 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a, 0xfe, 0x70, 0x12, 0x49, - 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2, 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, - 0xe4, 0x6a, 0x49, 0x04, 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12, - 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05, 0x11, 0xfe, 0xe3, 0x00, - 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, - 0xfe, 0x21, 0x00, 0xa1, 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08, - 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01, 0x86, 0x24, 0x06, 0x12, - 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d, 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, - 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe, - 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13, 0x47, 0x01, 0xa7, 0x26, - 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19, 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, - 0x1f, 0xfe, 0xfe, 0x05, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c, - 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x14, - 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48, 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, - 0x48, 0x8b, 0x1c, 0x3d, 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04, - 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68, 0x06, 0x11, 0x9a, 0x01, - 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4, 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, - 0x70, 0x01, 0x6e, 0x87, 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe, - 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07, 0x8d, 0x81, 0x02, 0x22, - 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, - 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32, - 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15, 0xfe, 0x1b, 0x00, 0x01, - 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, - 0x08, 0x15, 0x00, 0x02, 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d, - 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, - 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, - 0x81, 0x8c, 0xfe, 0x5c, 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02, - 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x77, 0xfe, 0xca, - 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a, 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, - 0x74, 0xfe, 0x80, 0x80, 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1, - 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f, 0x40, 0x12, 0x58, 0x01, - 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, - 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, - 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a, 0xfe, 0x2a, 0x12, 0xfe, - 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, - 0x1f, 0x80, 0x12, 0x58, 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe, - 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x39, 0x18, 0x3a, - 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35, 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, - 0x08, 0xfe, 0x9e, 0xf0, 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80, - 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x7a, 0x08, 0x8d, - 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10, 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, - 0xfe, 0x10, 0x12, 0x61, 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c, - 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe, 0x52, 0x12, 0xfe, 0x2c, - 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, - 0xaa, 0xfe, 0xf3, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe, - 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xb5, 0xfe, - 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, - 0xb8, 0x6d, 0xb9, 0x6d, 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33, - 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a, 0xfe, 0x74, 0x18, 0x1c, - 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01, 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, - 0x74, 0x67, 0x1a, 0x02, 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe, - 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc, 0xfe, 0x83, 0x80, 0xfe, - 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, - 0xfe, 0xc1, 0x59, 0x77, 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf, - 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e, 0x79, 0x56, 0x68, 0x57, - 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, - 0x0c, 0x7c, 0x79, 0x56, 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39, - 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x10, 0x58, 0xfe, - 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, - 0x04, 0xfe, 0xf7, 0x00, 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe, - 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08, 0x11, 0x9b, 0x09, 0x04, - 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a, 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, - 0x8d, 0x58, 0x02, 0x6d, 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12, - 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9, 0x14, 0x7a, 0x01, 0x33, - 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, - 0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10, - 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x84, 0x05, 0xcb, 0x1c, - 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00, 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, - 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca, - 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe, 0x22, 0x00, 0x02, 0x5a, - 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe, 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, - 0xec, 0x0a, 0x0f, 0x93, 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10, - 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00, 0x2a, 0x13, 0xfe, 0x4e, - 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0, 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, - 0xdd, 0xb8, 0x22, 0xb9, 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48, - 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xdb, 0x10, 0x11, 0xfe, - 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd, 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, - 0xbc, 0x7d, 0xbd, 0x7f, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42, - 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c, 0x09, 0x04, 0x0b, 0xfe, - 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54, 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, - 0x0c, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, - 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x02, 0x29, - 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e, 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, - 0xfe, 0xaa, 0x10, 0x01, 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe, - 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01, 0xe8, 0x59, 0x11, 0x2d, - 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02, 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, - 0x0b, 0x0f, 0x00, 0xfe, 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe, - 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, - 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35, 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, - 0x04, 0xe6, 0x0b, 0x5f, 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00, - 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa, 0xab, 0x70, 0x05, 0x6b, - 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, - 0xda, 0x02, 0x29, 0xea, 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01, - 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e, 0x1d, 0xfe, 0xce, 0x45, - 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47, 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, - 0x98, 0x56, 0xfe, 0x38, 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d, - 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, - 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe, 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, - 0x3e, 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e, - 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12, 0xce, 0x1e, 0x2d, 0x47, - 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe, 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, - 0xe2, 0x15, 0x05, 0xfe, 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02, - 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, - 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, - 0xce, 0x62, 0x7a, 0xfe, 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01, - 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, - 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11, 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, - 0x4d, 0xfe, 0xf7, 0x12, 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24, - 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, - 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, - 0x03, 0x57, 0xb6, 0x23, 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04, - 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xe1, - 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe, 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, - 0x90, 0xfe, 0x30, 0xf4, 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d, - 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01, 0xe8, 0x11, 0xfe, 0xe9, - 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01, 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, - 0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe, - 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80, 0x40, 0x12, 0x20, 0x63, - 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, - 0x00, 0xfe, 0x06, 0x58, 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe, - 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x24, 0x69, 0x12, 0xc9, - 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48, 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, - 0x54, 0x21, 0xfe, 0x08, 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe, - 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c, 0x46, 0x1e, 0x20, 0xed, - 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, - 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d, - 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46, 0xfa, 0xef, 0xfe, 0x42, - 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, - 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, - 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e, 0x10, 0x07, 0x7e, 0x45, - 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03, 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, - 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe, - 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b, 0xfe, 0x48, 0x12, 0x07, - 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30, 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, - 0xfe, 0x23, 0x00, 0x16, 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe, - 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b, 0x01, 0x08, 0x8c, 0x43, - 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01, 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, - 0x2f, 0x07, 0x9b, 0xfe, 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04, - 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe, 0xc6, 0x10, 0x1e, 0x58, - 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77, 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, - 0x0c, 0x7b, 0x0c, 0x7c, 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1, - 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0xfe, - 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, - 0x83, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1, - 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e, 0x58, 0xfe, 0x1f, 0x40, - 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, - 0x50, 0xfe, 0xc6, 0x50, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39, - 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06, 0x12, 0xcd, 0x02, 0x5b, - 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5, 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, - 0x5b, 0x01, 0x6e, 0x1c, 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe, - 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, - 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19, 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, - 0x1f, 0xa2, 0x30, 0x2e, 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01, - 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44, 0x01, 0x08, 0x1f, 0xa2, - 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, - 0x04, 0x19, 0x34, 0x9f, 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda, - 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1, 0x05, 0xc6, 0x28, 0x84, - 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, - 0x05, 0x50, 0xb4, 0x0c, 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02, - 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06, 0x21, 0x44, 0x01, 0xfe, - 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14, 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, - 0x16, 0x44, 0xfe, 0x4a, 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05, - 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xd8, 0x14, 0x02, 0x5c, - 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe, 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, - 0x03, 0x8f, 0xfe, 0xdc, 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01, - 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0xfe, 0xff, 0x7f, - 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, - 0x3d, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, - 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58, 0x03, 0x0a, 0x50, 0x01, - 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c, 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, - 0x19, 0x48, 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27, - 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, - 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01, 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, - 0x89, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, - 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe, 0xcc, 0x12, 0x49, 0x04, - 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2, 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, - 0x06, 0x17, 0xc3, 0x78, 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83, - 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c, 0x13, 0x06, 0xfe, 0x56, - 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00, 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, - 0x13, 0x06, 0xfe, 0x28, 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4, - 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90, 0x01, 0xba, 0xfe, 0x4e, - 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4, 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, - 0x04, 0xf4, 0x6c, 0xfe, 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c, - 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba, 0xfe, 0x9c, 0x14, 0xb7, - 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, - 0x19, 0x83, 0x60, 0x23, 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe, - 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x0b, 0x01, - 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, - 0x15, 0x06, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08, - 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89, 0x4a, 0x01, 0x08, 0x03, - 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44, 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, - 0x3b, 0x72, 0x9f, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe, - 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd, 0x01, 0x43, 0x1e, 0xcd, - 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, - 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88, - 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3, 0x88, 0x03, 0x0a, 0x42, - 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, - 0xfe, 0x49, 0xe4, 0x10, 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17, - 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, - 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01, 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, - 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10, - 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58, 0x05, 0xfe, 0x66, 0x01, - 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, - 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6, - 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17, 0x10, 0x71, 0xfe, 0x83, - 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, - 0x94, 0x14, 0xfe, 0x10, 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, - 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71, 0xfe, 0x30, 0xbc, 0xfe, - 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, - 0x16, 0xfe, 0x5c, 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02, - 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc, 0xfe, 0x1d, 0xf7, 0x4f, - 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, - 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63, - 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14, 0x06, 0x37, 0x95, 0xa9, - 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17, 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, - 0x13, 0x0d, 0x03, 0x71, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c, - 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x3c, 0x8a, 0x0a, - 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, - 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f, - 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xf6, 0xfe, 0xd6, 0xf0, - 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c, 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, - 0x27, 0x01, 0xda, 0x17, 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f, - 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68, 0xc8, 0xfe, 0x48, 0x55, - 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73, 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, - 0x0a, 0x40, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42, - 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01, 0x0e, 0x73, 0x75, 0x03, - 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18, 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, - 0xfe, 0x4e, 0xe4, 0xc2, 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b, - 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05, 0xfe, 0x94, 0x00, 0xfe, - 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, - 0x45, 0xfe, 0x0c, 0x12, 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe, - 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1b, 0xfe, 0x5a, - 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26, 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, - 0x0b, 0x5d, 0x24, 0x93, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14, - 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9, 0x03, 0x25, 0xfe, 0xca, - 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6, 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00, +static unsigned char _adv_asc3550_buf[] = { + 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc, + 0x01, 0x00, 0x48, 0xe4, + 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0x00, 0xfa, 0xff, 0xff, + 0x28, 0x0e, 0x9e, 0xe7, + 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, + 0x55, 0xf0, 0x01, 0xf6, + 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00, + 0x00, 0xec, 0x85, 0xf0, + 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54, 0x00, 0xe6, 0x1e, 0xf0, + 0x86, 0xf0, 0xb4, 0x00, + 0x98, 0x57, 0xd0, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, + 0xaa, 0x18, 0x02, 0x80, + 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40, + 0x00, 0x57, 0x01, 0xea, + 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x3e, 0x57, 0x00, 0x80, + 0x03, 0xe6, 0xb6, 0x00, + 0xc0, 0x00, 0x01, 0x01, 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, + 0x02, 0x4a, 0xb9, 0x54, + 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00, + 0x3e, 0x00, 0x80, 0x00, + 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, + 0x74, 0x01, 0x76, 0x01, + 0x78, 0x01, 0x62, 0x0a, 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, + 0x4c, 0x1c, 0xbb, 0x55, + 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0, + 0x03, 0xf7, 0x06, 0xf7, + 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00, 0x00, 0x01, 0xb0, 0x08, + 0x30, 0x13, 0x64, 0x15, + 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, + 0x04, 0xea, 0x5d, 0xf0, + 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, + 0xcc, 0x00, 0x20, 0x01, + 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10, 0x0a, 0x12, 0x04, 0x13, + 0x40, 0x13, 0x30, 0x1c, + 0x00, 0x4e, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, + 0x59, 0xf0, 0xa7, 0xf0, + 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, + 0xa4, 0x00, 0xb5, 0x00, + 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xde, 0x03, 0x56, 0x0a, + 0x14, 0x0e, 0x02, 0x10, + 0x04, 0x10, 0x0a, 0x10, 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, + 0x10, 0x15, 0x14, 0x15, + 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, + 0x91, 0x44, 0x0a, 0x45, + 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55, 0xb0, 0x57, 0x01, 0x58, + 0x83, 0x59, 0x05, 0xe6, + 0x0b, 0xf0, 0x0c, 0xf0, 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, + 0x02, 0xfa, 0x03, 0xfa, + 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00, + 0x9e, 0x00, 0xa8, 0x00, + 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, + 0x7a, 0x01, 0xc0, 0x01, + 0xc2, 0x01, 0x7c, 0x02, 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, + 0x69, 0x08, 0xba, 0x08, + 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10, + 0xf1, 0x10, 0x06, 0x12, + 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13, 0x42, 0x14, 0xd6, 0x14, + 0x8a, 0x15, 0xc6, 0x17, + 0xd2, 0x17, 0x6b, 0x18, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, + 0x0e, 0x47, 0x48, 0x47, + 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55, + 0x14, 0x56, 0x77, 0x57, + 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90, 0x03, 0xa1, 0xfe, 0x9c, + 0xf0, 0x29, 0x02, 0xfe, + 0xb8, 0x0c, 0xff, 0x10, 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, + 0xfe, 0x80, 0x01, 0xff, + 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, + 0x00, 0xfe, 0x57, 0x24, + 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00, 0x00, 0x10, 0xff, 0x09, + 0x00, 0x00, 0xff, 0x08, + 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, + 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, + 0xfe, 0x04, 0xf7, 0xcf, + 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe, 0x04, 0xf7, 0xcf, 0x67, + 0x0b, 0x3c, 0x2a, 0xfe, + 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, + 0xfe, 0xf0, 0x01, 0xfe, + 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b, + 0x02, 0xfe, 0xd4, 0x0c, + 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28, + 0x1c, 0x05, 0xfe, 0xa6, + 0x00, 0xfe, 0xd3, 0x12, 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, + 0xf0, 0xfe, 0x86, 0x02, + 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02, + 0xfe, 0x46, 0xf0, 0xfe, + 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02, 0xfe, 0x43, 0xf0, 0xfe, + 0x44, 0x02, 0xfe, 0x44, + 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, + 0xa0, 0x17, 0x06, 0x18, + 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe, + 0x1e, 0x1c, 0xfe, 0xe9, + 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xc7, + 0x0a, 0x6b, 0x01, 0x9e, + 0x02, 0x29, 0x14, 0x4d, 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, + 0x01, 0x82, 0xfe, 0xbd, + 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, + 0x58, 0x1c, 0x17, 0x06, + 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0, 0xfe, 0x02, 0x02, 0x21, + 0xfe, 0x94, 0x02, 0xfe, + 0x5a, 0x1c, 0xea, 0xfe, 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, + 0x01, 0xfe, 0x54, 0x0f, + 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe, + 0x69, 0x10, 0x17, 0x06, + 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d, 0x12, 0x20, 0xfe, 0x05, + 0xf6, 0xc7, 0x01, 0xfe, + 0x52, 0x16, 0x09, 0x4a, 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, + 0x02, 0x29, 0x0a, 0x40, + 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41, + 0x58, 0x0a, 0x99, 0x01, + 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03, 0x01, 0xe6, 0x02, 0x29, + 0x2a, 0x46, 0xfe, 0x02, + 0xe8, 0x27, 0xf8, 0xfe, 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, + 0x01, 0xfe, 0x07, 0x4b, + 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0, + 0xfe, 0x56, 0x03, 0xfe, + 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0, 0x9c, 0xfe, 0xef, 0x10, + 0xfe, 0x9f, 0xf0, 0xfe, + 0x64, 0x03, 0xeb, 0x0f, 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, + 0x1c, 0xeb, 0x09, 0x04, + 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40, + 0x01, 0x0e, 0xac, 0x75, + 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2, 0xfe, 0x01, 0xf0, 0xd2, + 0xfe, 0x82, 0xf0, 0xfe, + 0x92, 0x03, 0xec, 0x11, 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, + 0x32, 0x1f, 0xfe, 0xb4, + 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe, + 0x0a, 0xf0, 0xfe, 0x7a, + 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe, 0xf6, 0x04, 0x14, 0x2c, + 0x01, 0x33, 0x8f, 0xfe, + 0x66, 0x02, 0x02, 0xd1, 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, + 0xf7, 0xfe, 0x48, 0x1c, + 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3, + 0x0a, 0xca, 0x01, 0x0e, + 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28, 0xfe, 0x10, 0x12, 0x14, + 0x2c, 0x01, 0x33, 0x8f, + 0xfe, 0x66, 0x02, 0x02, 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, + 0xfe, 0x3c, 0x04, 0x1f, + 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, + 0x12, 0x2b, 0xff, 0x02, + 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04, 0x2b, 0x01, 0x08, 0x1f, + 0x22, 0x30, 0x2e, 0xd5, + 0xfe, 0x4c, 0x44, 0xfe, 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, + 0xfe, 0x4c, 0x54, 0x64, + 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d, + 0xfe, 0x2a, 0x13, 0x2f, + 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64, + 0xd3, 0xfa, 0xef, 0x86, + 0x09, 0x04, 0x1d, 0xfe, 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, + 0x1d, 0xfe, 0x1c, 0x12, + 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, + 0x70, 0x0c, 0x02, 0x22, + 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90, 0xf9, 0x03, 0x14, 0x92, + 0x01, 0x33, 0x02, 0x29, + 0xfe, 0x42, 0x5b, 0x67, 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, + 0x80, 0xfe, 0x31, 0xe4, + 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a, + 0xfe, 0x70, 0x12, 0x49, + 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2, 0x00, 0x28, 0x16, 0xfe, + 0x80, 0x05, 0xfe, 0x31, + 0xe4, 0x6a, 0x49, 0x04, 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, + 0x28, 0xfe, 0x42, 0x12, + 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05, + 0x11, 0xfe, 0xe3, 0x00, + 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05, 0xfe, 0x49, 0xf0, 0xfe, + 0x64, 0x05, 0x83, 0x24, + 0xfe, 0x21, 0x00, 0xa1, 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, + 0x09, 0x48, 0x01, 0x08, + 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01, + 0x86, 0x24, 0x06, 0x12, + 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d, 0xfe, 0x22, 0x12, 0x47, + 0x01, 0xa7, 0x14, 0x92, + 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, + 0x02, 0x22, 0x05, 0xfe, + 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13, + 0x47, 0x01, 0xa7, 0x26, + 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19, 0xfe, 0x02, 0x12, 0x5f, + 0x01, 0xfe, 0xaa, 0x14, + 0x1f, 0xfe, 0xfe, 0x05, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, + 0x05, 0x50, 0xb4, 0x0c, + 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a, + 0x13, 0x01, 0xfe, 0x14, + 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48, 0xb7, 0x19, 0x13, 0x6c, + 0xff, 0x02, 0x00, 0x57, + 0x48, 0x8b, 0x1c, 0x3d, 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, + 0x72, 0x06, 0x49, 0x04, + 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68, + 0x06, 0x11, 0x9a, 0x01, + 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4, 0x0c, 0x3f, 0x17, 0x06, + 0x01, 0xa7, 0xec, 0x72, + 0x70, 0x01, 0x6e, 0x87, 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, + 0xfe, 0x0a, 0xf0, 0xfe, + 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07, + 0x8d, 0x81, 0x02, 0x22, + 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a, 0x01, 0x08, 0x15, 0x00, + 0x01, 0x08, 0x15, 0x00, + 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, + 0x00, 0x02, 0xfe, 0x32, + 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15, + 0xfe, 0x1b, 0x00, 0x01, + 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, + 0x08, 0x15, 0x06, 0x01, + 0x08, 0x15, 0x00, 0x02, 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, + 0x9a, 0x81, 0x4b, 0x1d, + 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca, + 0x45, 0xfe, 0x32, 0x12, + 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, + 0xfe, 0x32, 0x07, 0x8d, + 0x81, 0x8c, 0xfe, 0x5c, 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, + 0x06, 0x15, 0x19, 0x02, + 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae, + 0x90, 0x77, 0xfe, 0xca, + 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a, 0x35, 0x1e, 0x20, 0x07, + 0x10, 0xfe, 0x0e, 0x12, + 0x74, 0xfe, 0x80, 0x80, 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, + 0x83, 0xe7, 0xc4, 0xa1, + 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f, + 0x40, 0x12, 0x58, 0x01, + 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, + 0x51, 0x83, 0xfb, 0xfe, + 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, + 0xfe, 0x40, 0x50, 0xfe, + 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a, + 0xfe, 0x2a, 0x12, 0xfe, + 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x04, 0x4f, + 0x85, 0x01, 0xa8, 0xfe, + 0x1f, 0x80, 0x12, 0x58, 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, + 0x18, 0x57, 0xfb, 0xfe, + 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, + 0x0c, 0x39, 0x18, 0x3a, + 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35, 0x2a, 0x13, 0xfe, 0x4e, + 0x11, 0x65, 0xfe, 0x48, + 0x08, 0xfe, 0x9e, 0xf0, 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, + 0xdd, 0xb8, 0xfe, 0x80, + 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0, + 0xfe, 0x7a, 0x08, 0x8d, + 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10, 0x15, 0x19, 0xfe, 0xc9, + 0x10, 0x61, 0x04, 0x06, + 0xfe, 0x10, 0x12, 0x61, 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, + 0x12, 0xfe, 0x2e, 0x1c, + 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe, + 0x52, 0x12, 0xfe, 0x2c, + 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0xbe, + 0x08, 0xfe, 0x8a, 0x10, + 0xaa, 0xfe, 0xf3, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, + 0x24, 0x0a, 0xab, 0xfe, + 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe, + 0x1c, 0x12, 0xb5, 0xfe, + 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a, 0x16, 0x9d, 0x05, 0xcb, + 0x1c, 0x06, 0x16, 0x9d, + 0xb8, 0x6d, 0xb9, 0x6d, 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, + 0x14, 0x92, 0x01, 0x33, + 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a, + 0xfe, 0x74, 0x18, 0x1c, + 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01, 0xfe, 0x44, 0x0d, 0x3b, + 0x01, 0xe6, 0x1e, 0x27, + 0x74, 0x67, 0x1a, 0x02, 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, + 0x09, 0x04, 0x6a, 0xfe, + 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc, + 0xfe, 0x83, 0x80, 0xfe, + 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x63, + 0x27, 0xfe, 0x40, 0x59, + 0xfe, 0xc1, 0x59, 0x77, 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, + 0x7c, 0xbe, 0x54, 0xbf, + 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e, + 0x79, 0x56, 0x68, 0x57, + 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05, 0xfa, 0x4e, 0x01, 0xa5, + 0xa2, 0x23, 0x0c, 0x7b, + 0x0c, 0x7c, 0x79, 0x56, 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, + 0x16, 0xd7, 0x79, 0x39, + 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53, + 0xfe, 0x10, 0x58, 0xfe, + 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x02, 0x6d, 0x09, 0x04, + 0x19, 0x16, 0xd7, 0x09, + 0x04, 0xfe, 0xf7, 0x00, 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, + 0xfe, 0x10, 0x90, 0xfe, + 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08, + 0x11, 0x9b, 0x09, 0x04, + 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a, 0x77, 0xfe, 0xc6, 0x08, + 0xfe, 0x0c, 0x58, 0xfe, + 0x8d, 0x58, 0x02, 0x6d, 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, + 0x0b, 0xfe, 0x1a, 0x12, + 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9, + 0x14, 0x7a, 0x01, 0x33, + 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0xbe, 0x39, + 0xfe, 0xed, 0x19, 0xbf, + 0x3a, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, + 0x34, 0xfe, 0x74, 0x10, + 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a, + 0x84, 0x05, 0xcb, 0x1c, + 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00, 0x02, 0x5a, 0xfe, 0xd1, + 0xf0, 0xfe, 0xc4, 0x0a, + 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, + 0xce, 0xf0, 0xfe, 0xca, + 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe, + 0x22, 0x00, 0x02, 0x5a, + 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe, 0x24, 0x00, 0x02, 0x5a, + 0xfe, 0xd0, 0xf0, 0xfe, + 0xec, 0x0a, 0x0f, 0x93, 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, + 0x4c, 0xfe, 0x10, 0x10, + 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00, + 0x2a, 0x13, 0xfe, 0x4e, + 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0, 0xfe, 0x20, 0x0b, 0xb1, + 0x16, 0x32, 0x2a, 0x73, + 0xdd, 0xb8, 0x22, 0xb9, 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, + 0x32, 0x8c, 0xfe, 0x48, + 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe, + 0xdb, 0x10, 0x11, 0xfe, + 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd, 0x7f, 0xfe, 0x89, 0xf0, + 0x22, 0x30, 0x2e, 0xd8, + 0xbc, 0x7d, 0xbd, 0x7f, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, + 0x45, 0x0f, 0xfe, 0x42, + 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c, + 0x09, 0x04, 0x0b, 0xfe, + 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54, 0x12, 0x4b, 0xfe, 0x28, + 0x00, 0x21, 0xfe, 0xa6, + 0x0c, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, + 0xfe, 0xe2, 0x10, 0x01, + 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d, + 0x01, 0x6f, 0x02, 0x29, + 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e, 0x0b, 0xfe, 0xb4, 0x10, + 0x01, 0x86, 0x3e, 0x0b, + 0xfe, 0xaa, 0x10, 0x01, 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, + 0x3e, 0x0b, 0x0f, 0xfe, + 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01, + 0xe8, 0x59, 0x11, 0x2d, + 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02, 0xfe, 0x2a, 0x03, 0x09, + 0x04, 0x0b, 0x84, 0x3e, + 0x0b, 0x0f, 0x00, 0xfe, 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, + 0x09, 0x04, 0x1b, 0xfe, + 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe, + 0x1c, 0x1c, 0xfe, 0x9d, + 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35, 0xfe, 0xa9, 0x10, 0x0f, + 0xfe, 0x15, 0x00, 0xfe, + 0x04, 0xe6, 0x0b, 0x5f, 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, + 0x0f, 0xfe, 0x47, 0x00, + 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa, + 0xab, 0x70, 0x05, 0x6b, + 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b, 0xfe, 0x9d, 0x41, 0xfe, + 0x1c, 0x42, 0x59, 0x01, + 0xda, 0x02, 0x29, 0xea, 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, + 0x00, 0x37, 0x97, 0x01, + 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e, + 0x1d, 0xfe, 0xce, 0x45, + 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47, 0x4b, 0x89, 0xfe, 0x75, + 0x57, 0x05, 0x51, 0xfe, + 0x98, 0x56, 0xfe, 0x38, 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, + 0x46, 0x09, 0x04, 0x1d, + 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a, + 0x99, 0x01, 0x0e, 0xfe, + 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe, 0x2a, 0x03, 0x0a, 0x51, + 0xfe, 0xee, 0x14, 0xee, + 0x3e, 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, + 0x13, 0x02, 0x29, 0x1e, + 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12, + 0xce, 0x1e, 0x2d, 0x47, + 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe, 0xec, 0x0d, 0x13, 0x06, + 0x12, 0x4d, 0x01, 0xfe, + 0xe2, 0x15, 0x05, 0xfe, 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, + 0xf0, 0x0d, 0xfe, 0x02, + 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05, + 0xf6, 0xfe, 0x34, 0x01, + 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, 0x18, 0x13, + 0xaf, 0xfe, 0x02, 0xea, + 0xce, 0x62, 0x7a, 0xfe, 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, + 0x05, 0xfe, 0x38, 0x01, + 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01, + 0x0c, 0xfe, 0x62, 0x01, + 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11, 0x2d, 0x8a, 0x13, 0x06, + 0x03, 0x23, 0x03, 0x1e, + 0x4d, 0xfe, 0xf7, 0x12, 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, + 0x71, 0x13, 0xfe, 0x24, + 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03, + 0xdc, 0xfe, 0x73, 0x57, + 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc, 0xfe, 0x5b, 0x57, 0xfe, + 0x80, 0x5d, 0x03, 0xfe, + 0x03, 0x57, 0xb6, 0x23, 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, + 0x75, 0x03, 0x09, 0x04, + 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13, + 0xfe, 0x1e, 0x80, 0xe1, + 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe, 0x0e, 0x13, 0xfe, 0x0e, + 0x90, 0xa3, 0xfe, 0x3c, + 0x90, 0xfe, 0x30, 0xf4, 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, + 0x16, 0x2f, 0x07, 0x2d, + 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01, + 0xe8, 0x11, 0xfe, 0xe9, + 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01, 0xfe, 0x14, 0x16, 0xfe, + 0x1e, 0x1c, 0xfe, 0x14, + 0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, + 0x09, 0x04, 0x4f, 0xfe, + 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80, + 0x40, 0x12, 0x20, 0x63, + 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x03, 0xfe, 0x08, + 0x1c, 0x05, 0xfe, 0xac, + 0x00, 0xfe, 0x06, 0x58, 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, + 0xfe, 0xb0, 0x00, 0xfe, + 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, + 0x24, 0x69, 0x12, 0xc9, + 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48, 0x5f, 0x17, 0x1d, 0xfe, + 0x90, 0x4d, 0xfe, 0x91, + 0x54, 0x21, 0xfe, 0x08, 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, + 0xfe, 0x90, 0x4d, 0xfe, + 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c, + 0x46, 0x1e, 0x20, 0xed, + 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x32, 0x0f, 0xea, + 0x70, 0xfe, 0x14, 0x1c, + 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, + 0xfe, 0x07, 0xe6, 0x1d, + 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46, + 0xfa, 0xef, 0xfe, 0x42, + 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a, 0x42, 0x01, 0x0e, 0xb0, + 0xfe, 0x36, 0x12, 0xf0, + 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, + 0x3d, 0x75, 0x07, 0x10, + 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e, + 0x10, 0x07, 0x7e, 0x45, + 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03, 0xfe, 0x44, 0x58, 0x74, + 0xfe, 0x01, 0xec, 0x97, + 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, + 0x27, 0x01, 0xda, 0xfe, + 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b, + 0xfe, 0x48, 0x12, 0x07, + 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30, 0x12, 0x07, 0xc2, 0x16, + 0xfe, 0x3e, 0x11, 0x07, + 0xfe, 0x23, 0x00, 0x16, 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, + 0x11, 0x07, 0x19, 0xfe, + 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b, + 0x01, 0x08, 0x8c, 0x43, + 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01, 0xfe, 0x32, 0x0e, 0x11, + 0x7e, 0x02, 0x29, 0x2b, + 0x2f, 0x07, 0x9b, 0xfe, 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, + 0xfc, 0x10, 0x09, 0x04, + 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe, + 0xc6, 0x10, 0x1e, 0x58, + 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77, 0xfe, 0x82, 0x0c, 0x0c, + 0x54, 0x18, 0x55, 0x23, + 0x0c, 0x7b, 0x0c, 0x7c, 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, + 0xa5, 0xc0, 0x38, 0xc1, + 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe, + 0x05, 0xfa, 0x4e, 0xfe, + 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, + 0x0c, 0x56, 0x18, 0x57, + 0x83, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, + 0x00, 0x56, 0xfe, 0xa1, + 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e, + 0x58, 0xfe, 0x1f, 0x40, + 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x05, 0x56, + 0x31, 0x57, 0xfe, 0x44, + 0x50, 0xfe, 0xc6, 0x50, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, + 0x8a, 0x50, 0x05, 0x39, + 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06, + 0x12, 0xcd, 0x02, 0x5b, + 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5, 0x07, 0x06, 0x21, 0x44, + 0x2f, 0x07, 0x9b, 0x21, + 0x5b, 0x01, 0x6e, 0x1c, 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, + 0x39, 0x68, 0x3a, 0xfe, + 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c, + 0x51, 0xfe, 0x8e, 0x51, + 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19, 0x41, 0x02, 0x5b, 0x2b, + 0x01, 0x08, 0x25, 0x32, + 0x1f, 0xa2, 0x30, 0x2e, 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, + 0x3b, 0x02, 0x44, 0x01, + 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44, + 0x01, 0x08, 0x1f, 0xa2, + 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x60, 0x05, 0xfe, 0x9c, + 0x00, 0x28, 0x84, 0x49, + 0x04, 0x19, 0x34, 0x9f, 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, + 0x78, 0x3d, 0xfe, 0xda, + 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1, + 0x05, 0xc6, 0x28, 0x84, + 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, + 0x14, 0xfe, 0x03, 0x17, + 0x05, 0x50, 0xb4, 0x0c, 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, + 0xfe, 0xaa, 0x14, 0x02, + 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06, + 0x21, 0x44, 0x01, 0xfe, + 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14, 0xfe, 0xa4, 0x14, 0x87, + 0xfe, 0x4a, 0xf4, 0x0b, + 0x16, 0x44, 0xfe, 0x4a, 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, + 0x85, 0x02, 0x5b, 0x05, + 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, + 0xd8, 0x14, 0x02, 0x5c, + 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe, 0xe0, 0x12, 0x72, 0xf1, + 0x01, 0x08, 0x23, 0x72, + 0x03, 0x8f, 0xfe, 0xdc, 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, + 0x12, 0x5e, 0x2b, 0x01, + 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, + 0x1c, 0xfe, 0xff, 0x7f, + 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, + 0x57, 0x48, 0x8b, 0x1c, + 0x3d, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, + 0x00, 0x57, 0x48, 0x8b, + 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58, + 0x03, 0x0a, 0x50, 0x01, + 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c, 0x10, 0xff, 0x03, 0x00, + 0x54, 0xfe, 0x00, 0xf4, + 0x19, 0x48, 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, + 0x03, 0x7c, 0x63, 0x27, + 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08, + 0xfe, 0x82, 0x4a, 0xfe, + 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01, 0xfe, 0x14, 0x18, 0xfe, + 0x42, 0x48, 0x5f, 0x60, + 0x89, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, + 0x1f, 0xfe, 0xa2, 0x14, + 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe, + 0xcc, 0x12, 0x49, 0x04, + 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2, 0x4b, 0xc3, 0x64, 0xfe, + 0xe8, 0x13, 0x3b, 0x13, + 0x06, 0x17, 0xc3, 0x78, 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, + 0xa1, 0xff, 0x02, 0x83, + 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c, + 0x13, 0x06, 0xfe, 0x56, + 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00, 0x8e, 0xe4, 0x0a, 0xfe, + 0x64, 0x00, 0x17, 0x93, + 0x13, 0x06, 0xfe, 0x28, 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, + 0xc8, 0x00, 0x8e, 0xe4, + 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90, + 0x01, 0xba, 0xfe, 0x4e, + 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4, 0x94, 0xfe, 0x56, 0xf0, + 0xfe, 0x60, 0x14, 0xfe, + 0x04, 0xf4, 0x6c, 0xfe, 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, + 0xfe, 0x22, 0x13, 0x1c, + 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba, + 0xfe, 0x9c, 0x14, 0xb7, + 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x19, 0xba, + 0xfe, 0x9c, 0x14, 0xb7, + 0x19, 0x83, 0x60, 0x23, 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, + 0xfe, 0xb4, 0x56, 0xfe, + 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26, + 0xe5, 0x15, 0x0b, 0x01, + 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xe5, 0x72, 0xfe, 0x89, + 0x49, 0x01, 0x08, 0x03, + 0x15, 0x06, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, + 0x15, 0x06, 0x01, 0x08, + 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89, + 0x4a, 0x01, 0x08, 0x03, + 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44, 0x13, 0xad, 0x12, 0xcc, + 0xfe, 0x49, 0xf4, 0x00, + 0x3b, 0x72, 0x9f, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, + 0x08, 0x2f, 0x07, 0xfe, + 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd, + 0x01, 0x43, 0x1e, 0xcd, + 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03, 0x0a, 0x42, 0x01, 0x0e, + 0xed, 0x88, 0x07, 0x10, + 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, + 0x80, 0x01, 0x0e, 0x88, + 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3, + 0x88, 0x03, 0x0a, 0x42, + 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x42, 0x01, 0x0e, + 0xfe, 0x80, 0x80, 0xf2, + 0xfe, 0x49, 0xe4, 0x10, 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, + 0x01, 0x82, 0x03, 0x17, + 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, + 0xfe, 0x24, 0x1c, 0xfe, + 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01, 0xfe, 0xfc, 0x16, 0xe0, + 0x91, 0x1d, 0x66, 0xfe, + 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, + 0xda, 0x10, 0x17, 0x10, + 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58, + 0x05, 0xfe, 0x66, 0x01, + 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06, + 0xfe, 0x3c, 0x50, 0x66, + 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, + 0x40, 0x16, 0xfe, 0xb6, + 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17, + 0x10, 0x71, 0xfe, 0x83, + 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x38, 0x90, + 0xfe, 0x62, 0x16, 0xfe, + 0x94, 0x14, 0xfe, 0x10, 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, + 0xfe, 0x98, 0xe7, 0x00, + 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71, + 0xfe, 0x30, 0xbc, 0xfe, + 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, + 0xc5, 0x90, 0xfe, 0x9a, + 0x16, 0xfe, 0x5c, 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, + 0x42, 0x10, 0xfe, 0x02, + 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc, + 0xfe, 0x1d, 0xf7, 0x4f, + 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x91, 0x4f, + 0x47, 0xfe, 0x83, 0x58, + 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, + 0xfe, 0xdd, 0x00, 0x63, + 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14, + 0x06, 0x37, 0x95, 0xa9, + 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17, 0x23, 0x03, 0xfe, 0x7e, + 0x18, 0x1c, 0x1a, 0x5d, + 0x13, 0x0d, 0x03, 0x71, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, + 0xe1, 0x10, 0x78, 0x2c, + 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42, + 0x13, 0x3c, 0x8a, 0x0a, + 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01, + 0xe3, 0xfe, 0x00, 0xcc, + 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, + 0x0e, 0xf2, 0x01, 0x6f, + 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, + 0xf6, 0xfe, 0xd6, 0xf0, + 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c, 0xe7, 0x0b, 0x0f, 0xfe, + 0x15, 0x00, 0x59, 0x76, + 0x27, 0x01, 0xda, 0x17, 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, + 0x11, 0x2d, 0x01, 0x6f, + 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68, + 0xc8, 0xfe, 0x48, 0x55, + 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73, 0x12, 0x98, 0x03, 0x0a, + 0x99, 0x01, 0x0e, 0xf0, + 0x0a, 0x40, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, + 0x75, 0x03, 0x0a, 0x42, + 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01, + 0x0e, 0x73, 0x75, 0x03, + 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18, 0x05, 0xfe, 0x90, 0x00, + 0xfe, 0x3a, 0x45, 0x5b, + 0xfe, 0x4e, 0xe4, 0xc2, 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, + 0xfe, 0x02, 0xe6, 0x1b, + 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05, + 0xfe, 0x94, 0x00, 0xfe, + 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe, 0x96, 0x00, 0xfe, 0x02, + 0xe6, 0x2c, 0xfe, 0x4e, + 0x45, 0xfe, 0x0c, 0x12, 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, + 0x03, 0x07, 0x7a, 0xfe, + 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, + 0x07, 0x1b, 0xfe, 0x5a, + 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26, 0x10, 0x07, 0x1a, 0x5d, + 0x24, 0x2c, 0xdc, 0x07, + 0x0b, 0x5d, 0x24, 0x93, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, + 0x9f, 0xad, 0x03, 0x14, + 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9, + 0x03, 0x25, 0xfe, 0xca, + 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6, 0x18, 0x03, 0xff, 0x1a, + 0x00, 0x00, }; -STATIC unsigned short _adv_asc3550_size = - sizeof(_adv_asc3550_buf); /* 0x13AD */ -STATIC ADV_DCNT _adv_asc3550_chksum = - 0x04D52DDDUL; /* Expanded little-endian checksum. */ +static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */ +static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */ /* Microcode buffer is kept after initialization for error recovery. */ -STATIC unsigned char _adv_asc38C0800_buf[] = { - 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4, 0x01, 0x00, 0x48, 0xe4, - 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19, 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, - 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, - 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0, 0x18, 0xf4, 0x08, 0x00, - 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0, 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, - 0x98, 0x57, 0x01, 0xfc, 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00, - 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13, 0xba, 0x13, 0x18, 0x40, - 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc, 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, - 0x76, 0x01, 0xb9, 0x54, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01, - 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12, 0x08, 0x12, 0x02, 0x4a, - 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, - 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, - 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d, 0x06, 0x13, 0x4c, 0x1c, - 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, - 0xbe, 0x00, 0x00, 0x01, 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44, - 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa, 0x05, 0x00, 0x34, 0x00, - 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, - 0x0c, 0x10, 0x22, 0x11, 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54, - 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, - 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc, 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, - 0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03, - 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13, 0x12, 0x13, 0x24, 0x14, - 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, - 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55, - 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0, 0x04, 0xf8, - 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, - 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01, - 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08, 0x68, 0x08, 0x69, 0x08, - 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f, 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, - 0x2a, 0x11, 0x06, 0x12, 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14, - 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18, 0xca, 0x18, 0xe6, 0x19, - 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, - 0xac, 0x0d, 0xff, 0x10, 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff, - 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, 0x00, 0xfe, 0x57, 0x24, - 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00, 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, - 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11, - 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, 0xfe, 0x04, 0xf7, 0xd6, - 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe, 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, - 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, - 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d, 0x02, 0xfe, 0xc8, 0x0d, - 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, - 0x00, 0xfe, 0xd3, 0x12, 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02, - 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02, 0xfe, 0x46, 0xf0, 0xfe, - 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, - 0xf0, 0xfe, 0x4c, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14, - 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, - 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, - 0x02, 0x2b, 0x15, 0x59, 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd, - 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, 0x58, 0x1c, 0x18, 0x06, - 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, - 0x5a, 0x1c, 0xf8, 0xfe, 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, - 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe, 0x69, 0x10, 0x18, 0x06, - 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43, 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, - 0x4a, 0x17, 0x08, 0x54, 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, - 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x09, - 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe, 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, - 0x2c, 0x4f, 0xfe, 0x02, 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, - 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x40, 0x1c, 0x1c, - 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, - 0xa7, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02, - 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13, 0x21, 0x22, 0xa3, 0xb7, - 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78, 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, - 0xfe, 0x01, 0xf0, 0xd9, 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27, - 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe, 0x06, 0xf0, 0xfe, 0xc8, - 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a, 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, - 0xfa, 0x04, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19, - 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x74, 0x01, 0xaf, 0x8c, - 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda, 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, - 0x2a, 0x03, 0x70, 0x28, 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, - 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d, 0xfe, 0x3c, 0x04, 0x3b, - 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, - 0x1d, 0xfe, 0xe4, 0x04, 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe, - 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0x4f, 0x79, 0x2a, - 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, - 0x07, 0x82, 0xfe, 0x52, 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe, - 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x08, 0x13, 0x32, 0x07, - 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, - 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6, - 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36, 0x02, 0x2b, 0xfe, 0x42, - 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, - 0x31, 0xe4, 0x5b, 0x08, 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c, - 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28, 0x17, 0xfe, 0x90, 0x05, - 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe, 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, - 0x4e, 0x12, 0x67, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48, - 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0x12, 0xfe, 0xe3, 0x00, - 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, - 0xfe, 0x21, 0x00, 0xab, 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02, - 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2, 0x08, 0x53, 0x05, 0xcb, - 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39, 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, - 0x12, 0x41, 0x01, 0xb2, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, - 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb, 0x03, 0x5c, 0x28, 0xfe, - 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18, 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, - 0x12, 0x50, 0x01, 0xfe, 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, - 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62, 0x12, 0x03, 0x45, 0x28, - 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01, 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, - 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2, - 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01, 0xfe, 0xcc, 0x15, 0x1d, - 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, - 0x18, 0x06, 0x01, 0xb2, 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb, - 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, - 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05, 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, - 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01, - 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38, 0x12, 0x08, 0x05, 0x1a, - 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, - 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe, - 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b, 0xfe, 0x09, 0x6f, 0xba, - 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d, 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, - 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01, - 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe, 0x2c, 0x90, 0xfe, 0xae, - 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, - 0x11, 0xfe, 0x0e, 0x12, 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe, - 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b, 0x37, 0x01, 0xb3, 0xb8, - 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, - 0xfe, 0xc6, 0x51, 0x88, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c, - 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d, 0x14, 0x3e, 0xfe, 0x4a, - 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, - 0x61, 0x08, 0x05, 0x5b, 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe, - 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, - 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d, 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, - 0x49, 0x0c, 0x63, 0x08, 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e, - 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe, 0x9a, 0x08, 0xc6, 0xfe, - 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, - 0x01, 0x4b, 0xfe, 0xc9, 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12, - 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e, 0x1c, 0x02, 0xfe, 0x18, - 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a, 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, - 0xf0, 0xfe, 0xd2, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7, - 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18, 0xfe, 0xf1, 0x18, 0xfe, - 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, - 0x59, 0x1c, 0x85, 0xfe, 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5, - 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18, 0x0b, 0xb6, 0xfe, 0xbf, - 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, - 0xf0, 0x85, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5, - 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15, 0x9d, 0x01, 0x36, 0x10, - 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10, 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, - 0xe4, 0x0a, 0xfe, 0x1a, 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe, - 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0x08, 0x05, - 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f, 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, - 0x18, 0xfe, 0xed, 0x18, 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49, - 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18, 0x8f, 0xfe, 0xe3, 0x54, - 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, - 0xf0, 0xfe, 0x60, 0x09, 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b, - 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00, 0xad, 0xfe, 0x01, 0x59, - 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a, 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, - 0x54, 0x57, 0x49, 0x7d, 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b, - 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63, 0x02, 0x4a, 0x08, 0x05, - 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe, 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, - 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a, - 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29, 0x61, 0x0c, 0x7f, 0x14, - 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8, 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, - 0x3a, 0x3f, 0x3b, 0x40, 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef, - 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40, 0xe4, 0x08, 0x05, 0x1f, - 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, - 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05, - 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19, 0x81, 0x50, 0xfe, 0x10, - 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32, 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, - 0x08, 0x05, 0x0a, 0xfe, 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c, - 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7, 0x08, 0x05, 0x0a, 0xfe, - 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, - 0x01, 0x36, 0x10, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed, - 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe, 0x00, 0xff, 0x35, 0xfe, - 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6, 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, - 0xd2, 0x1e, 0x06, 0xfe, 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe, - 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, - 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, - 0x02, 0x65, 0xfe, 0xcb, 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0, - 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea, 0x0b, 0x10, 0x58, 0xfe, - 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05, 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, - 0xfe, 0x4e, 0x11, 0x27, 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34, - 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20, 0x0c, 0x1c, 0x34, 0x94, - 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6, 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, - 0x12, 0xfe, 0xe8, 0x00, 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33, - 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24, 0x33, 0x31, 0xdf, 0xbc, - 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c, 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, - 0x08, 0x05, 0x0a, 0xfe, 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28, - 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x44, 0xfe, 0x28, 0x00, - 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09, 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, - 0x01, 0x73, 0x02, 0x2b, 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10, - 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xac, - 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96, 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, - 0xf6, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08, - 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05, 0x1a, 0xfe, 0x58, 0x12, - 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, - 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10, - 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10, 0xfe, 0x13, 0x00, 0xfe, - 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41, 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, - 0xb6, 0x74, 0x03, 0x70, 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe, - 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0, 0xb4, 0x15, 0xfe, 0x31, - 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02, 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, - 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75, - 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x44, 0x48, - 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09, 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, - 0xa4, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d, - 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0xce, 0x47, 0xfe, 0xad, - 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, - 0xd5, 0x22, 0x2f, 0x41, 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06, - 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe, 0x3a, 0x01, 0x56, 0xfe, - 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00, 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, - 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe, - 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13, 0x15, 0x1a, 0x39, 0xa0, - 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, - 0x03, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12, - 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12, 0x22, 0x9f, 0xb7, 0x13, - 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24, 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, - 0x10, 0xc3, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc, - 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21, 0xfe, 0x00, 0xcc, 0x04, - 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05, 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, - 0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe, - 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x0a, 0xfe, 0x3c, 0x50, - 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f, 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, - 0x4e, 0x01, 0xf5, 0x01, 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01, - 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90, 0x0c, 0xfe, 0x64, 0x01, - 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe, 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, - 0xec, 0x20, 0xfe, 0x80, 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79, - 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, - - 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, - 0x58, 0xfe, 0x0a, 0x1c, 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52, - 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc, 0x0f, 0x44, 0x11, 0x0f, - 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, - 0x7c, 0x6f, 0x4f, 0x22, 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, - 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x04, 0x42, - 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, - 0xb0, 0x7c, 0x6f, 0x4f, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f, - 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, - 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, - 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14, - 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d, 0xfe, 0x01, 0xec, 0xa2, - 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, - 0xdd, 0x10, 0x2c, 0xc7, 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07, - 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17, 0xfe, 0x32, 0x12, 0x07, - 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17, 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, - 0x07, 0x00, 0x17, 0x24, 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d, - 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d, 0x32, 0x07, 0xa6, 0xfe, - 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe, 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, - 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03, - 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21, 0x0c, 0x7f, 0x0c, 0x80, - 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01, 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, - 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f, - 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40, 0x88, 0x9b, 0x2e, 0x9c, - 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, - 0x5f, 0x08, 0x05, 0x5a, 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61, - 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50, - 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, - 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d, - 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23, 0x72, 0x01, 0xaf, 0x1e, - 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a, 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, - 0x8b, 0x55, 0x57, 0x3d, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19, - 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, - 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a, 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, - 0xe8, 0x33, 0x31, 0xdf, 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8, - 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53, 0x05, 0x1f, 0x35, 0xa9, - 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06, 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, - 0xfe, 0x4b, 0x45, 0xee, 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35, - 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x03, 0x5c, 0xc1, 0x0c, - 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, - 0x34, 0x1d, 0x4c, 0x33, 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1, - 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a, 0xf4, 0x06, 0xea, 0x32, - 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, - 0x01, 0xfe, 0xcc, 0x15, 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13, - 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0, 0x13, 0x1c, 0xfe, 0xd0, - 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01, 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, - 0x00, 0x57, 0x52, 0x93, 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f, - 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, - 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, - 0x93, 0xfe, 0x0b, 0x58, 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03, - 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52, 0xfe, 0x00, 0x7d, 0xfe, - 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, - 0x7d, 0x40, 0x04, 0xdd, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01, - 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, - 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, - 0x03, 0xcd, 0x28, 0xfe, 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee, - 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c, 0x30, 0xfe, 0x78, 0x10, - 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83, 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, - 0x96, 0xf2, 0x18, 0x6d, 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00, - 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28, 0x10, 0x69, 0x06, 0xfe, - 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2, 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, - 0x88, 0x98, 0xfe, 0x90, 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe, - 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4, 0x9e, 0xfe, 0xf3, 0x10, - 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e, 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, - 0x6e, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, - 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d, 0xf4, 0x00, 0xe9, 0x91, - 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, - 0x0b, 0x26, 0xf3, 0x16, 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76, - 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x19, 0x01, 0x0b, - 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, - 0xfe, 0x89, 0x4a, 0x01, 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8, - 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, - 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, - 0xfe, 0x20, 0x13, 0x1d, 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06, - 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e, 0x07, 0x11, 0xae, 0x09, - 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, - 0xe7, 0x11, 0x07, 0x11, 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e, - 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xfe, 0x80, 0x4c, - 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, - 0x04, 0x18, 0x11, 0x75, 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, - 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4, 0x17, 0xad, 0x9a, 0x1b, - 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04, 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, - 0x18, 0x11, 0x75, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe, - 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, - 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, - 0xfe, 0xb6, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75, - 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x2e, 0x97, 0xfe, 0x5a, - 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c, 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, - 0x04, 0xb9, 0x23, 0xfe, 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe, - 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0xcb, 0x97, 0xfe, 0x92, - 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, - 0xf6, 0x11, 0x75, 0xfe, 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d, - 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0x9a, 0x5b, 0x41, 0xfe, - 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, - 0x00, 0x6a, 0x2a, 0x04, 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39, - 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04, 0xfe, 0x7e, 0x18, 0x1e, - 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2, 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, - 0x7c, 0x6f, 0x4f, 0x32, 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09, - 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, - 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, - 0x01, 0x73, 0xfe, 0x16, 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14, - 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c, 0xe7, 0x0a, 0x10, 0xfe, - 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18, 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, - 0x12, 0x2f, 0x01, 0x73, 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b, - 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77, 0x13, 0xa3, 0x04, 0x09, - 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46, 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, - 0x18, 0x77, 0x78, 0x04, 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09, - 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe, 0x1c, 0x19, 0x03, 0xfe, - 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, - 0x03, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b, - 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe, 0x08, 0x10, 0x03, 0xfe, - 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e, 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, - 0x1e, 0x6e, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00, - 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19, 0x04, 0x07, 0x7e, 0xfe, - 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, - 0xf0, 0xfe, 0x92, 0x19, 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07, - 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59, 0xa9, 0xb8, 0x04, 0x15, - 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe, 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, - 0xf7, 0xfe, 0x14, 0xf0, 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0, - 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00, +static unsigned char _adv_asc38C0800_buf[] = { + 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4, + 0x01, 0x00, 0x48, 0xe4, + 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19, 0x00, 0xfa, 0xff, 0xff, + 0x1c, 0x0f, 0x00, 0xf6, + 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, + 0x09, 0xe7, 0x55, 0xf0, + 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0, + 0x18, 0xf4, 0x08, 0x00, + 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0, 0x82, 0x0d, 0x00, 0xe6, + 0x86, 0xf0, 0xb1, 0xf0, + 0x98, 0x57, 0x01, 0xfc, 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, + 0x3c, 0x00, 0xbb, 0x00, + 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13, + 0xba, 0x13, 0x18, 0x40, + 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc, 0x3e, 0x00, 0x6c, 0x01, + 0x6e, 0x01, 0x74, 0x01, + 0x76, 0x01, 0xb9, 0x54, 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, + 0xc0, 0x00, 0x01, 0x01, + 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12, + 0x08, 0x12, 0x02, 0x4a, + 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, + 0x5d, 0xf0, 0x02, 0xfa, + 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, + 0x68, 0x01, 0x6a, 0x01, + 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d, + 0x06, 0x13, 0x4c, 0x1c, + 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x0c, 0x00, + 0x0f, 0x00, 0x47, 0x00, + 0xbe, 0x00, 0x00, 0x01, 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, + 0x4e, 0x1c, 0x10, 0x44, + 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa, + 0x05, 0x00, 0x34, 0x00, + 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4a, 0x0b, + 0x42, 0x0c, 0x12, 0x0f, + 0x0c, 0x10, 0x22, 0x11, 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, + 0x00, 0x4e, 0x42, 0x54, + 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, + 0x59, 0xf0, 0xb8, 0xf0, + 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc, 0x05, 0xfc, 0x06, 0x00, + 0x19, 0x00, 0x33, 0x00, + 0x9b, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, + 0xe7, 0x00, 0xe2, 0x03, + 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13, + 0x12, 0x13, 0x24, 0x14, + 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17, 0x20, 0x1c, 0x34, 0x1c, + 0x36, 0x1c, 0x08, 0x44, + 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, + 0x3a, 0x55, 0x83, 0x55, + 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, + 0x0c, 0xf0, 0x04, 0xf8, + 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00, 0x1e, 0x00, 0x9e, 0x00, + 0xa8, 0x00, 0xaa, 0x00, + 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, + 0xc4, 0x01, 0xc6, 0x01, + 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08, + 0x68, 0x08, 0x69, 0x08, + 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f, 0x12, 0x10, 0x1a, 0x10, + 0xed, 0x10, 0xf1, 0x10, + 0x2a, 0x11, 0x06, 0x12, 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, + 0x1e, 0x13, 0x46, 0x14, + 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18, + 0xca, 0x18, 0xe6, 0x19, + 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0xfe, 0x9c, + 0xf0, 0x2b, 0x02, 0xfe, + 0xac, 0x0d, 0xff, 0x10, 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, + 0xfe, 0x84, 0x01, 0xff, + 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, + 0x00, 0xfe, 0x57, 0x24, + 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00, 0x00, 0x11, 0xff, 0x09, + 0x00, 0x00, 0xff, 0x08, + 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, + 0xff, 0xff, 0xff, 0x11, + 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, + 0xfe, 0x04, 0xf7, 0xd6, + 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe, 0x04, 0xf7, 0xd6, 0x99, + 0x0a, 0x42, 0x2c, 0xfe, + 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, + 0xfe, 0xf4, 0x01, 0xfe, + 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d, + 0x02, 0xfe, 0xc8, 0x0d, + 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe, 0xfc, 0x10, 0xfe, 0x28, + 0x1c, 0x03, 0xfe, 0xa6, + 0x00, 0xfe, 0xd3, 0x12, 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, + 0xf0, 0xfe, 0x8a, 0x02, + 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02, + 0xfe, 0x46, 0xf0, 0xfe, + 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x43, 0xf0, 0xfe, + 0x48, 0x02, 0xfe, 0x44, + 0xf0, 0xfe, 0x4c, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, + 0xaa, 0x18, 0x06, 0x14, + 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe, + 0x1e, 0x1c, 0xfe, 0xe9, + 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xce, + 0x09, 0x70, 0x01, 0xa8, + 0x02, 0x2b, 0x15, 0x59, 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, + 0x01, 0x87, 0xfe, 0xbd, + 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, + 0x58, 0x1c, 0x18, 0x06, + 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0, 0xfe, 0x06, 0x02, 0x23, + 0xfe, 0x98, 0x02, 0xfe, + 0x5a, 0x1c, 0xf8, 0xfe, 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, + 0x01, 0xfe, 0x48, 0x10, + 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe, + 0x69, 0x10, 0x18, 0x06, + 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43, 0x13, 0x20, 0xfe, 0x05, + 0xf6, 0xce, 0x01, 0xfe, + 0x4a, 0x17, 0x08, 0x54, 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, + 0x82, 0x16, 0x02, 0x2b, + 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10, + 0xfe, 0x41, 0x58, 0x09, + 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe, 0x10, 0x03, 0x01, 0xfe, + 0x82, 0x16, 0x02, 0x2b, + 0x2c, 0x4f, 0xfe, 0x02, 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, + 0xfe, 0x77, 0x57, 0xfe, + 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7, + 0xfe, 0x40, 0x1c, 0x1c, + 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x48, + 0x03, 0xfe, 0x11, 0xf0, + 0xa7, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, + 0xfe, 0x11, 0x00, 0x02, + 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13, + 0x21, 0x22, 0xa3, 0xb7, + 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78, 0x01, 0xfe, 0xb4, 0x16, + 0x12, 0xd1, 0x1c, 0xd9, + 0xfe, 0x01, 0xf0, 0xd9, 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, + 0xfe, 0xe4, 0x00, 0x27, + 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe, + 0x06, 0xf0, 0xfe, 0xc8, + 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a, 0x06, 0x02, 0x24, 0x03, + 0x70, 0x28, 0x17, 0xfe, + 0xfa, 0x04, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, + 0xf9, 0x2c, 0x99, 0x19, + 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, + 0x74, 0x01, 0xaf, 0x8c, + 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda, 0x09, 0xd1, 0x01, 0x0e, + 0x8d, 0x51, 0x64, 0x79, + 0x2a, 0x03, 0x70, 0x28, 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, + 0xfe, 0x6a, 0x02, 0x02, + 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d, + 0xfe, 0x3c, 0x04, 0x3b, + 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e, 0x12, 0x2d, 0xff, 0x02, + 0x00, 0x10, 0x01, 0x0b, + 0x1d, 0xfe, 0xe4, 0x04, 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, + 0xfe, 0x4c, 0x44, 0xfe, + 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, + 0xda, 0x4f, 0x79, 0x2a, + 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62, 0x13, 0x08, 0x05, 0x1b, + 0xfe, 0x2a, 0x13, 0x32, + 0x07, 0x82, 0xfe, 0x52, 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, + 0x54, 0x6b, 0xda, 0xfe, + 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe, + 0x08, 0x13, 0x32, 0x07, + 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x1c, 0x12, 0x15, 0x9d, + 0x08, 0x05, 0x06, 0x4d, + 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, + 0x2d, 0x12, 0xfe, 0xe6, + 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36, + 0x02, 0x2b, 0xfe, 0x42, + 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, + 0xfe, 0x87, 0x80, 0xfe, + 0x31, 0xe4, 0x5b, 0x08, 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, + 0x07, 0x19, 0xfe, 0x7c, + 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28, + 0x17, 0xfe, 0x90, 0x05, + 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe, 0x56, 0x13, 0x03, 0xfe, + 0xa0, 0x00, 0x28, 0xfe, + 0x4e, 0x12, 0x67, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, + 0x34, 0xfe, 0x89, 0x48, + 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05, + 0x12, 0xfe, 0xe3, 0x00, + 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05, 0xfe, 0x49, 0xf0, 0xfe, + 0x70, 0x05, 0x88, 0x25, + 0xfe, 0x21, 0x00, 0xab, 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, + 0x09, 0x48, 0xff, 0x02, + 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2, + 0x08, 0x53, 0x05, 0xcb, + 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39, 0xfe, 0x27, 0x01, 0x08, + 0x05, 0x1b, 0xfe, 0x22, + 0x12, 0x41, 0x01, 0xb2, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, + 0x0d, 0x00, 0x01, 0x36, + 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb, + 0x03, 0x5c, 0x28, 0xfe, + 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18, 0x06, 0x09, 0x06, 0x53, + 0x05, 0x1f, 0xfe, 0x02, + 0x12, 0x50, 0x01, 0xfe, 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, + 0x01, 0x4b, 0x12, 0xfe, + 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62, + 0x12, 0x03, 0x45, 0x28, + 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01, 0xfe, 0x76, 0x19, 0xfe, + 0x43, 0x48, 0xc4, 0xcc, + 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, + 0x6e, 0x41, 0x01, 0xb2, + 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01, + 0xfe, 0xcc, 0x15, 0x1d, + 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe, 0xe5, 0x00, 0x03, + 0x45, 0xc1, 0x0c, 0x45, + 0x18, 0x06, 0x01, 0xb2, 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, + 0xe2, 0x00, 0x27, 0xdb, + 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07, + 0xfe, 0x06, 0xf0, 0xfe, + 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05, 0x0a, 0xfe, 0x2e, 0x12, + 0x16, 0x19, 0x01, 0x0b, + 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, + 0xfe, 0x99, 0xa4, 0x01, + 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38, + 0x12, 0x08, 0x05, 0x1a, + 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, + 0x0b, 0x16, 0x00, 0x01, + 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, + 0xe2, 0x6c, 0x58, 0xbe, + 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b, + 0xfe, 0x09, 0x6f, 0xba, + 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d, 0x8b, 0x6c, 0x7f, 0x27, + 0xfe, 0x54, 0x07, 0x1c, + 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, + 0x07, 0x02, 0x24, 0x01, + 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe, + 0x2c, 0x90, 0xfe, 0xae, + 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x54, 0x5a, + 0x37, 0x22, 0x20, 0x07, + 0x11, 0xfe, 0x0e, 0x12, 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, + 0xfe, 0x06, 0x10, 0xfe, + 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b, + 0x37, 0x01, 0xb3, 0xb8, + 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe, 0x08, 0x50, 0xfe, 0x8a, + 0x50, 0xfe, 0x44, 0x51, + 0xfe, 0xc6, 0x51, 0x88, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, + 0x14, 0x5f, 0xfe, 0x0c, + 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d, + 0x14, 0x3e, 0xfe, 0x4a, + 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, + 0x90, 0x0c, 0x60, 0x14, + 0x61, 0x08, 0x05, 0x5b, 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, + 0xfe, 0x44, 0x90, 0xfe, + 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, + 0x0c, 0x5e, 0x14, 0x5f, + 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d, 0x14, 0x3e, 0x0c, 0x2e, + 0x14, 0x3c, 0x21, 0x0c, + 0x49, 0x0c, 0x63, 0x08, 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, + 0x27, 0xdd, 0xfe, 0x9e, + 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe, + 0x9a, 0x08, 0xc6, 0xfe, + 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x94, 0x08, + 0x95, 0x86, 0x02, 0x24, + 0x01, 0x4b, 0xfe, 0xc9, 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, + 0x06, 0xfe, 0x10, 0x12, + 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e, + 0x1c, 0x02, 0xfe, 0x18, + 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a, 0xfe, 0x7a, 0x12, 0xfe, + 0x2c, 0x1c, 0xfe, 0xaa, + 0xf0, 0xfe, 0xd2, 0x09, 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, + 0xde, 0x09, 0xfe, 0xb7, + 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18, + 0xfe, 0xf1, 0x18, 0xfe, + 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, + 0x14, 0x59, 0xfe, 0x95, + 0x59, 0x1c, 0x85, 0xfe, 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, + 0xfe, 0xf0, 0x08, 0xb5, + 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18, + 0x0b, 0xb6, 0xfe, 0xbf, + 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, + 0x12, 0xc2, 0xfe, 0xd2, + 0xf0, 0x85, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, + 0x06, 0x17, 0x85, 0xc5, + 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15, + 0x9d, 0x01, 0x36, 0x10, + 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10, 0x80, 0x02, 0x65, 0xfe, + 0x98, 0x80, 0xfe, 0x19, + 0xe4, 0x0a, 0xfe, 0x1a, 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, + 0xfe, 0x44, 0x54, 0xbe, + 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08, + 0x02, 0x4a, 0x08, 0x05, + 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f, 0x14, 0x40, 0x9b, 0x2e, + 0x9c, 0x3c, 0xfe, 0x6c, + 0x18, 0xfe, 0xed, 0x18, 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, + 0x3b, 0x40, 0x03, 0x49, + 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18, + 0x8f, 0xfe, 0xe3, 0x54, + 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a, 0xfe, 0x37, 0xf0, 0xfe, + 0xda, 0x09, 0xfe, 0x8b, + 0xf0, 0xfe, 0x60, 0x09, 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, + 0x0a, 0x3a, 0x49, 0x3b, + 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00, + 0xad, 0xfe, 0x01, 0x59, + 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a, 0xfe, 0x24, 0x0a, 0x3a, + 0x49, 0x8f, 0xfe, 0xe3, + 0x54, 0x57, 0x49, 0x7d, 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, + 0x4a, 0x3a, 0x49, 0x3b, + 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63, + 0x02, 0x4a, 0x08, 0x05, + 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe, 0x66, 0x13, 0x22, 0x62, + 0xb7, 0xfe, 0x03, 0xa1, + 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, + 0xfe, 0x86, 0x91, 0x6a, + 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29, + 0x61, 0x0c, 0x7f, 0x14, + 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8, 0x6a, 0x2a, 0x13, 0x62, + 0x9b, 0x2e, 0x9c, 0x3c, + 0x3a, 0x3f, 0x3b, 0x40, 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, + 0xfa, 0x3c, 0x01, 0xef, + 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40, + 0xe4, 0x08, 0x05, 0x1f, + 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, + 0x03, 0x5e, 0x29, 0x5f, + 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, + 0xf4, 0x09, 0x08, 0x05, + 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19, + 0x81, 0x50, 0xfe, 0x10, + 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32, 0x07, 0xa6, 0x17, 0xfe, + 0x08, 0x09, 0x12, 0xa6, + 0x08, 0x05, 0x0a, 0xfe, 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, + 0x08, 0x09, 0xfe, 0x0c, + 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7, + 0x08, 0x05, 0x0a, 0xfe, + 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xf4, 0xc2, 0xfe, 0xd1, + 0xf0, 0xe2, 0x15, 0x7e, + 0x01, 0x36, 0x10, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, + 0x57, 0x3d, 0xfe, 0xed, + 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe, + 0x00, 0xff, 0x35, 0xfe, + 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6, 0x0b, 0xfe, 0x76, 0x18, + 0x1e, 0x19, 0x8a, 0x03, + 0xd2, 0x1e, 0x06, 0xfe, 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, + 0xfe, 0xd1, 0xf0, 0xfe, + 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42, + 0x10, 0xfe, 0xce, 0xf0, + 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xca, 0x0b, + 0x10, 0xfe, 0x22, 0x00, + 0x02, 0x65, 0xfe, 0xcb, 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, + 0x02, 0x65, 0xfe, 0xd0, + 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea, + 0x0b, 0x10, 0x58, 0xfe, + 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05, 0x1f, 0x4d, 0x10, 0xfe, + 0x12, 0x00, 0x2c, 0x0f, + 0xfe, 0x4e, 0x11, 0x27, 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, + 0x0c, 0xbc, 0x17, 0x34, + 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20, + 0x0c, 0x1c, 0x34, 0x94, + 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6, 0xdc, 0x02, 0x24, 0x01, + 0x4b, 0xfe, 0xdb, 0x10, + 0x12, 0xfe, 0xe8, 0x00, 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, + 0x89, 0xf0, 0x24, 0x33, + 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24, + 0x33, 0x31, 0xdf, 0xbc, + 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c, 0x06, 0xfe, 0x81, 0x49, + 0x17, 0xfe, 0x2c, 0x0d, + 0x08, 0x05, 0x0a, 0xfe, 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, + 0x12, 0x55, 0xfe, 0x28, + 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, + 0x44, 0xfe, 0x28, 0x00, + 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09, 0xa4, 0x01, 0xfe, 0x26, + 0x0f, 0x64, 0x12, 0x2f, + 0x01, 0x73, 0x02, 0x2b, 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, + 0x0a, 0xfe, 0xb4, 0x10, + 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82, + 0xfe, 0x34, 0x46, 0xac, + 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96, 0x10, 0x08, 0x54, 0x0a, + 0x37, 0x01, 0xf5, 0x01, + 0xf6, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, + 0xfe, 0x2e, 0x03, 0x08, + 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05, + 0x1a, 0xfe, 0x58, 0x12, + 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, + 0xfe, 0x50, 0x0d, 0xfe, + 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, + 0xfe, 0xa9, 0x10, 0x10, + 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10, + 0xfe, 0x13, 0x00, 0xfe, + 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41, 0x00, 0xaa, 0x10, 0xfe, + 0x24, 0x00, 0x8c, 0xb5, + 0xb6, 0x74, 0x03, 0x70, 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, + 0xfe, 0x9d, 0x41, 0xfe, + 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0, + 0xb4, 0x15, 0xfe, 0x31, + 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02, 0xd7, 0x42, 0xfe, 0x06, + 0xec, 0xd0, 0xfc, 0x44, + 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, + 0x4b, 0x91, 0xfe, 0x75, + 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01, + 0x0e, 0xfe, 0x44, 0x48, + 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09, 0x46, 0x01, 0x0e, 0x41, + 0xfe, 0x41, 0x58, 0x09, + 0xa4, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, + 0x2e, 0x03, 0x09, 0x5d, + 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe, + 0xce, 0x47, 0xfe, 0xad, + 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x9e, 0x12, 0x21, 0x13, + 0x59, 0x13, 0x9f, 0x13, + 0xd5, 0x22, 0x2f, 0x41, 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, + 0xe0, 0x0e, 0x0f, 0x06, + 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe, + 0x3a, 0x01, 0x56, 0xfe, + 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00, 0x66, 0xfe, 0x04, 0xec, + 0x20, 0x4f, 0xfe, 0x05, + 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, + 0x48, 0xf4, 0x0d, 0xfe, + 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13, + 0x15, 0x1a, 0x39, 0xa0, + 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x1e, 0xfe, 0xf0, 0xff, + 0x0c, 0xfe, 0x60, 0x01, + 0x03, 0xfe, 0x3a, 0x01, 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, + 0x06, 0x13, 0x2f, 0x12, + 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12, + 0x22, 0x9f, 0xb7, 0x13, + 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24, 0x1c, 0x15, 0x19, 0x39, + 0xa0, 0xb4, 0xfe, 0xd9, + 0x10, 0xc3, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, + 0xc3, 0xfe, 0x03, 0xdc, + 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21, + 0xfe, 0x00, 0xcc, 0x04, + 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05, 0x58, 0xfe, 0x22, 0x13, + 0xfe, 0x1c, 0x80, 0x07, + 0x06, 0xfe, 0x1a, 0x13, 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, + 0xfe, 0x0c, 0x90, 0xfe, + 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4, + 0x0a, 0xfe, 0x3c, 0x50, + 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f, 0xad, 0x01, 0xfe, 0xb4, + 0x16, 0x08, 0x05, 0x1b, + 0x4e, 0x01, 0xf5, 0x01, 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, + 0xfe, 0x2c, 0x13, 0x01, + 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90, + 0x0c, 0xfe, 0x64, 0x01, + 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe, 0x12, 0x12, 0xfe, 0x03, + 0x80, 0x8d, 0xfe, 0x01, + 0xec, 0x20, 0xfe, 0x80, 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, + 0x22, 0x20, 0xfb, 0x79, + 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, + 0x03, 0xfe, 0xae, 0x00, + + 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, + 0xb2, 0x00, 0xfe, 0x09, + 0x58, 0xfe, 0x0a, 0x1c, 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, + 0x45, 0x0f, 0x46, 0x52, + 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc, + 0x0f, 0x44, 0x11, 0x0f, + 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xe4, + 0x25, 0x11, 0x13, 0x20, + 0x7c, 0x6f, 0x4f, 0x22, 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, + 0x56, 0xfe, 0xd6, 0xf0, + 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, + 0x18, 0x1c, 0x04, 0x42, + 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b, 0xfe, 0xce, 0x47, 0xfe, + 0xf5, 0x13, 0x04, 0x01, + 0xb0, 0x7c, 0x6f, 0x4f, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, + 0x13, 0x32, 0x07, 0x2f, + 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe, + 0x41, 0x48, 0xfe, 0x45, + 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, + 0x07, 0x11, 0xac, 0x09, + 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, + 0x82, 0x4e, 0xfe, 0x14, + 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d, + 0xfe, 0x01, 0xec, 0xa2, + 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1a, 0x79, + 0x2a, 0x01, 0xe3, 0xfe, + 0xdd, 0x10, 0x2c, 0xc7, 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, + 0xfe, 0x48, 0x12, 0x07, + 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17, + 0xfe, 0x32, 0x12, 0x07, + 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17, 0xfe, 0x9c, 0x12, 0x07, + 0x1f, 0xfe, 0x12, 0x12, + 0x07, 0x00, 0x17, 0x24, 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, + 0x94, 0x4b, 0x04, 0x2d, + 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d, + 0x32, 0x07, 0xa6, 0xfe, + 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe, 0xf0, 0x11, 0x08, 0x05, + 0x5a, 0xfe, 0x72, 0x12, + 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, + 0xfe, 0x26, 0x13, 0x03, + 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21, + 0x0c, 0x7f, 0x0c, 0x80, + 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01, 0xef, 0x9b, 0x2e, 0x9c, + 0x3c, 0xfe, 0x04, 0x55, + 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, + 0x91, 0x10, 0x03, 0x3f, + 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40, + 0x88, 0x9b, 0x2e, 0x9c, + 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x00, 0x56, 0xfe, 0xa1, + 0x56, 0x0c, 0x5e, 0x14, + 0x5f, 0x08, 0x05, 0x5a, 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, + 0x03, 0x60, 0x29, 0x61, + 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44, + 0x50, 0xfe, 0xc6, 0x50, + 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x3d, + 0x29, 0x3e, 0xfe, 0x40, + 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, + 0x2d, 0x01, 0x0b, 0x1d, + 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23, + 0x72, 0x01, 0xaf, 0x1e, + 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a, 0x3d, 0x3b, 0x3e, 0xfe, + 0x0a, 0x55, 0x35, 0xfe, + 0x8b, 0x55, 0x57, 0x3d, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, + 0x02, 0x72, 0xfe, 0x19, + 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34, + 0x1d, 0xe8, 0x33, 0x31, + 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a, 0x4d, 0x02, 0x4c, 0x01, + 0x0b, 0x1c, 0x34, 0x1d, + 0xe8, 0x33, 0x31, 0xdf, 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, + 0x33, 0x31, 0xfe, 0xe8, + 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53, + 0x05, 0x1f, 0x35, 0xa9, + 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06, 0x7c, 0x43, 0xfe, 0xda, + 0x14, 0x01, 0xaf, 0x8c, + 0xfe, 0x4b, 0x45, 0xee, 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, + 0x03, 0x45, 0x28, 0x35, + 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, + 0x03, 0x5c, 0xc1, 0x0c, + 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0x9e, 0x15, 0x02, + 0x89, 0x01, 0x0b, 0x1c, + 0x34, 0x1d, 0x4c, 0x33, 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, + 0xfe, 0x42, 0x58, 0xf1, + 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a, + 0xf4, 0x06, 0xea, 0x32, + 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x67, 0x2d, + 0x01, 0x0b, 0x26, 0x89, + 0x01, 0xfe, 0xcc, 0x15, 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, + 0x26, 0xfe, 0xd4, 0x13, + 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0, + 0x13, 0x1c, 0xfe, 0xd0, + 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01, 0x0b, 0xfe, 0xd5, 0x10, + 0x0f, 0x71, 0xff, 0x02, + 0x00, 0x57, 0x52, 0x93, 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, + 0x00, 0x5c, 0x04, 0x0f, + 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56, + 0xfe, 0x00, 0x5c, 0x04, + 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x04, 0x0f, 0x71, 0xff, + 0x02, 0x00, 0x57, 0x52, + 0x93, 0xfe, 0x0b, 0x58, 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, + 0x87, 0x04, 0xfe, 0x03, + 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52, + 0xfe, 0x00, 0x7d, 0xfe, + 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x6a, 0x2a, 0x0c, 0x5e, + 0x14, 0x5f, 0x57, 0x3f, + 0x7d, 0x40, 0x04, 0xdd, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, + 0x5a, 0x8d, 0x04, 0x01, + 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d, + 0xfe, 0x96, 0x15, 0x33, + 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15, 0x33, 0x31, 0xfe, 0xe8, + 0x0a, 0xfe, 0xc1, 0x59, + 0x03, 0xcd, 0x28, 0xfe, 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, + 0x21, 0x69, 0x1a, 0xee, + 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c, + 0x30, 0xfe, 0x78, 0x10, + 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83, 0x55, 0x69, 0x19, 0xae, + 0x98, 0xfe, 0x30, 0x00, + 0x96, 0xf2, 0x18, 0x6d, 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, + 0x98, 0xfe, 0x64, 0x00, + 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28, + 0x10, 0x69, 0x06, 0xfe, + 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2, 0x09, 0xfe, 0xc8, 0x00, + 0x18, 0x59, 0x0f, 0x06, + 0x88, 0x98, 0xfe, 0x90, 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, + 0x43, 0xf4, 0x9f, 0xfe, + 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4, + 0x9e, 0xfe, 0xf3, 0x10, + 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e, 0x43, 0xec, 0xfe, 0x00, + 0x17, 0xfe, 0x4d, 0xe4, + 0x6e, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, + 0x17, 0xfe, 0x4d, 0xe4, + 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d, + 0xf4, 0x00, 0xe9, 0x91, + 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x04, 0x51, 0x0f, 0x0a, + 0x04, 0x16, 0x06, 0x01, + 0x0b, 0x26, 0xf3, 0x16, 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, + 0x0b, 0x26, 0xf3, 0x76, + 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, + 0x16, 0x19, 0x01, 0x0b, + 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1, 0xfe, 0x89, 0x49, 0x01, + 0x0b, 0x26, 0xb1, 0x76, + 0xfe, 0x89, 0x4a, 0x01, 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, + 0xfe, 0x48, 0x13, 0xb8, + 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01, + 0xec, 0xfe, 0x27, 0x01, + 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x2e, 0x16, 0x32, + 0x07, 0xfe, 0xe3, 0x00, + 0xfe, 0x20, 0x13, 0x1d, 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, + 0x22, 0xd4, 0x07, 0x06, + 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e, + 0x07, 0x11, 0xae, 0x09, + 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x84, 0x01, + 0x0e, 0x8e, 0xfe, 0x80, + 0xe7, 0x11, 0x07, 0x11, 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, + 0x09, 0x48, 0x01, 0x0e, + 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80, + 0x80, 0xfe, 0x80, 0x4c, + 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, + 0x09, 0x5d, 0x01, 0x87, + 0x04, 0x18, 0x11, 0x75, 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, + 0x19, 0xde, 0xfe, 0x24, + 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4, + 0x17, 0xad, 0x9a, 0x1b, + 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04, 0xb9, 0x23, 0xfe, 0xde, + 0x16, 0xfe, 0xda, 0x10, + 0x18, 0x11, 0x75, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, + 0x18, 0x58, 0x03, 0xfe, + 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30, + 0xf4, 0x06, 0xfe, 0x3c, + 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x1f, + 0x97, 0xfe, 0x38, 0x17, + 0xfe, 0xb6, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, + 0x10, 0x18, 0x11, 0x75, + 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, + 0x2e, 0x97, 0xfe, 0x5a, + 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c, 0x1a, 0xfe, 0xaf, 0x19, + 0xfe, 0x98, 0xe7, 0x00, + 0x04, 0xb9, 0x23, 0xfe, 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, + 0xfe, 0x30, 0xbc, 0xfe, + 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, + 0xcb, 0x97, 0xfe, 0x92, + 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23, 0xfe, 0x7e, 0x17, 0xfe, + 0x42, 0x10, 0xfe, 0x02, + 0xf6, 0x11, 0x75, 0xfe, 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, + 0x03, 0xa1, 0xfe, 0x1d, + 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, + 0x9a, 0x5b, 0x41, 0xfe, + 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x11, 0xfe, 0x81, 0xe7, + 0x11, 0x12, 0xfe, 0xdd, + 0x00, 0x6a, 0x2a, 0x04, 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, + 0x17, 0x15, 0x06, 0x39, + 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04, + 0xfe, 0x7e, 0x18, 0x1e, + 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2, 0x1e, 0x06, 0xfe, 0xef, + 0x12, 0xfe, 0xe1, 0x10, + 0x7c, 0x6f, 0x4f, 0x32, 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, + 0x13, 0x42, 0x92, 0x09, + 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, + 0xf0, 0xfe, 0x00, 0xcc, + 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, + 0x0e, 0xfe, 0x80, 0x4c, + 0x01, 0x73, 0xfe, 0x16, 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, + 0x24, 0x12, 0xfe, 0x14, + 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c, + 0xe7, 0x0a, 0x10, 0xfe, + 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18, 0x06, 0x04, 0x42, 0x92, + 0x08, 0x54, 0x1b, 0x37, + 0x12, 0x2f, 0x01, 0x73, 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, + 0x90, 0x3a, 0xce, 0x3b, + 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77, + 0x13, 0xa3, 0x04, 0x09, + 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46, 0x01, 0x0e, 0xfe, 0x49, + 0x44, 0x17, 0xfe, 0xe8, + 0x18, 0x77, 0x78, 0x04, 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, + 0x5d, 0x01, 0xa8, 0x09, + 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe, + 0x1c, 0x19, 0x03, 0xfe, + 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xc9, + 0x6b, 0xfe, 0x2e, 0x19, + 0x03, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, + 0xfe, 0x0b, 0x00, 0x6b, + 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe, + 0x08, 0x10, 0x03, 0xfe, + 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e, 0x45, 0xea, 0xba, 0xff, + 0x04, 0x68, 0x54, 0xe7, + 0x1e, 0x6e, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, + 0x1a, 0xf4, 0xfe, 0x00, + 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19, + 0x04, 0x07, 0x7e, 0xfe, + 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10, + 0x07, 0x1a, 0xfe, 0x5a, + 0xf0, 0xfe, 0x92, 0x19, 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, + 0x25, 0x6d, 0xe5, 0x07, + 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59, + 0xa9, 0xb8, 0x04, 0x15, + 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe, 0x81, 0x03, 0x83, 0xfe, + 0x40, 0x5c, 0x04, 0x1c, + 0xf7, 0xfe, 0x14, 0xf0, 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, + 0xf7, 0xfe, 0x82, 0xf0, + 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00, }; -STATIC unsigned short _adv_asc38C0800_size = - sizeof(_adv_asc38C0800_buf); /* 0x14E1 */ -STATIC ADV_DCNT _adv_asc38C0800_chksum = - 0x050D3FD8UL; /* Expanded little-endian checksum. */ +static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */ +static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */ /* Microcode buffer is kept after initialization for error recovery. */ -STATIC unsigned char _adv_asc38C1600_buf[] = { - 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0, 0x18, 0xe4, 0x01, 0x00, - 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13, 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, - 0x00, 0xfa, 0xff, 0xff, 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0, - 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00, 0x98, 0x57, 0x01, 0xe6, - 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4, 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, - 0x10, 0x00, 0xc2, 0x0e, 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0, - 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01, 0x06, 0x13, 0x0c, 0x1c, - 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc, 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, - 0x62, 0x0a, 0x5a, 0x12, 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea, - 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, 0x04, 0x13, 0xbb, 0x55, - 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4, 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, - 0x00, 0x01, 0x01, 0x01, 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c, - 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, - 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, - 0xc6, 0x0e, 0x0c, 0x10, 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48, - 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x06, 0x00, - 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12, 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, - 0x10, 0x44, 0x00, 0x4c, 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0, - 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, - 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, - 0x68, 0x0d, 0x02, 0x10, 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16, - 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, - 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7, 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, - 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c, - 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x42, 0x1d, 0x08, 0x44, - 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, - 0x31, 0xe4, 0x02, 0xe6, 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, - 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0xa8, 0x00, 0xaa, 0x00, - 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01, 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, - 0xc8, 0x01, 0xca, 0x01, 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d, - 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10, 0xf3, 0x10, 0x06, 0x12, - 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13, 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, - 0xec, 0x0e, 0xff, 0x10, 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff, - 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, 0x00, 0xfe, 0x57, 0x24, - 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00, 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, - 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13, - 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, 0xfe, 0x04, 0xf7, 0xe8, - 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe, 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, - 0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, - 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d, 0x05, 0xfe, 0x08, 0x0f, - 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05, 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, - 0xa6, 0x00, 0xfe, 0xd1, 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90, - 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8, 0x02, 0xfe, 0x46, 0xf0, - 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60, 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, - 0x44, 0xf0, 0xfe, 0x52, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07, - 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02, 0x1c, 0xf5, 0xfe, 0x1e, - 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, - 0xa3, 0x05, 0x35, 0x1f, 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe, - 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe, 0x58, 0x1c, 0x1c, - 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, - 0xfe, 0x5a, 0x1c, 0xfe, 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01, - 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09, 0x1a, 0x31, 0xfe, 0x69, - 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, - 0xfe, 0x05, 0xf6, 0xde, 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51, - 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, - 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, - 0x7b, 0xfe, 0x1c, 0x03, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30, - 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0, 0xfe, 0xe4, 0x01, 0xfe, - 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40, 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, - 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f, - 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05, 0x70, 0x37, 0xfe, 0x48, - 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, - 0xb9, 0x0a, 0x57, 0x01, 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe, - 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32, 0x15, 0xfe, 0xe4, 0x00, - 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe, 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, - 0xd6, 0x03, 0xaf, 0xa0, 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b, - 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xfe, 0x46, 0x1c, - 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, - 0x01, 0xa6, 0x86, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77, - 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, - 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29, 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, - 0x7e, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01, - 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25, 0xee, 0xfe, 0x4c, 0x44, - 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, - 0x30, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe, - 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10, 0x13, 0x34, 0xfe, 0x4c, - 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, - 0x28, 0xa5, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f, - 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f, 0xfe, 0xa4, 0x0e, 0x05, - 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe, 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, - 0x0e, 0x8b, 0x02, 0x1f, 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46, - 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04, 0xfe, 0x87, 0x83, 0xfe, - 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, - 0x80, 0x04, 0xfe, 0xa0, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06, - 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda, 0x05, 0xd0, 0x54, 0x01, - 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, - 0x02, 0x00, 0x10, 0x2f, 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, - 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01, 0x38, 0xfe, 0x4a, 0xf0, - 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba, 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, - 0xfe, 0x22, 0x00, 0xa2, 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0, - 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe, 0x1c, 0x00, 0x4d, 0x01, - 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27, 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, - 0x3e, 0x01, 0x84, 0x1f, 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, - 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13, 0x03, 0xb6, 0x1e, 0xfe, - 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13, 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, - 0x07, 0x01, 0x38, 0x06, 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68, - 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x03, 0x9a, 0x1e, 0xfe, - 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13, 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, - 0x2e, 0x12, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00, - 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17, 0xfe, 0xea, 0x06, 0x01, - 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01, 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, - 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae, - 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a, 0x1e, 0xfe, 0x1a, 0x12, - 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, - 0xf0, 0x45, 0x0a, 0x95, 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6, - 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x17, 0xfe, - 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe, 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, - 0x41, 0x15, 0xe2, 0x21, 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05, - 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0x9c, 0x32, 0x5f, - 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00, 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, - 0xce, 0x07, 0xae, 0xfe, 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29, - 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, - 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, - 0xc6, 0x09, 0x01, 0x76, 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13, - 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, - 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00, 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, - 0x9a, 0x81, 0x04, 0xfe, 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c, - 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x53, 0x63, 0x4e, - 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, - 0xae, 0xfe, 0x96, 0x08, 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c, - 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe, 0x1e, 0xfe, 0x99, 0x58, - 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe, 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, - 0x61, 0x54, 0x44, 0x21, 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a, - 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40, 0x01, 0x0c, 0x61, 0x65, - 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, - 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e, - 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e, 0x01, 0xfe, 0xfe, 0x1e, - 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b, 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, - 0x54, 0xfe, 0x50, 0x12, 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b, - 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04, 0xfe, 0x9f, 0x83, 0x33, - 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90, 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, - 0x90, 0x04, 0xfe, 0xc6, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e, - 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90, 0x04, 0xfe, 0xc0, 0x93, - 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, - 0x10, 0x64, 0x22, 0x34, 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, - 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5, - 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a, 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, - 0xae, 0xfe, 0x12, 0x0a, 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41, - 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07, 0xfe, 0x14, 0x12, 0x01, - 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, - 0x1a, 0x0c, 0x01, 0x76, 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe, - 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe, 0x92, 0x10, 0xc4, 0xf6, - 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe, 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, - 0xf0, 0xbf, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0, - 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07, 0x1b, 0xbf, 0xd4, 0x5b, - 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5, 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, - 0x01, 0x42, 0x19, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74, - 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78, 0x0f, 0x4d, 0x01, 0xfe, - 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, - 0x0b, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21, - 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe, 0x83, 0x83, 0xfe, 0xc9, - 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42, 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, - 0x93, 0xfe, 0xca, 0x57, 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b, - 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0x10, - 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01, 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, - 0xdc, 0x34, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64, - 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97, 0x10, 0x98, 0x91, 0x6c, - 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, - 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, - 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x01, 0x0c, - 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe, 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, - 0xfe, 0x90, 0x93, 0x3a, 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe, - 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb, 0x01, 0x0c, 0x06, 0x0d, - 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e, 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, - 0x58, 0x05, 0x5b, 0x26, 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e, - 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, - 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef, 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, - 0xfe, 0x90, 0x10, 0xfe, 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51, - 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe, 0x76, 0x10, 0xac, 0xfe, - 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, - 0x08, 0x13, 0x19, 0xfe, 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92, - 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2, 0x0c, 0xfe, 0x3e, 0x10, - 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe, 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, - 0xea, 0x0c, 0x19, 0xfe, 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94, - 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3, 0xfe, 0xcc, 0xf0, 0xef, - 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12, 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, - 0x16, 0x0d, 0xfe, 0x9e, 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5, - 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32, 0x2f, 0xfe, 0x3e, 0x0d, - 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0, 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, - 0x05, 0x29, 0x01, 0x41, 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99, - 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8, 0x9c, 0x2f, 0xfe, 0x8c, - 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01, 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, - 0x90, 0x07, 0xfe, 0x81, 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13, - 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b, 0xfe, 0xda, 0x0e, 0x0a, - 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe, 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, - 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85, - 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe, 0xcc, 0x10, 0x01, 0xa7, - 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f, 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, - 0xcc, 0x47, 0x0b, 0x0e, 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2, - 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x40, 0x15, - 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01, 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, - 0x0c, 0x06, 0x0d, 0x5d, 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe, - 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, - 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, - 0xfe, 0x9f, 0x10, 0x19, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19, - 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19, 0xfe, 0x41, 0x00, 0xa2, - 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75, 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, - 0xe6, 0x12, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c, - 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01, 0xfe, 0xd4, 0x11, 0x05, - 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, - 0xfe, 0x06, 0xea, 0xe0, 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56, - 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01, 0x0c, 0x06, 0x28, 0xfe, - 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, - 0x49, 0x54, 0xb0, 0xfe, 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe, - 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x05, - 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12, 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, - 0xfe, 0x7c, 0x19, 0xfe, 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b, - 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe, 0xf0, 0x1a, 0x03, 0xfe, - 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe, 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, - 0x36, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b, - 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02, 0xea, 0xe7, 0x53, 0x92, - 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3, 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, - 0xfe, 0xf0, 0xff, 0x10, 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e, - 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02, 0x26, 0x02, 0x21, 0x96, - 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13, 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, - 0xcf, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe, - 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe, 0x00, 0xcc, 0x02, 0xfe, - 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, - 0x04, 0xfe, 0x9c, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80, - 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe, 0x1d, 0x80, 0x04, 0xfe, - 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c, 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, - 0x13, 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, - 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09, 0x56, 0xfb, 0x01, 0xfe, - 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, - 0xfe, 0xe9, 0x00, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e, - 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe, 0x96, 0x90, 0x04, 0xfe, - 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64, 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, - 0x65, 0xf9, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01, - 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40, 0x21, 0x2c, 0xfe, 0x00, - 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, - 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, - 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10, 0x66, 0x10, 0x55, 0x10, - 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, - 0x11, 0x46, 0x1a, 0x13, 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, - 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, - 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, - 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47, - 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01, 0xa7, 0x90, 0x34, 0x60, - 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, - 0x13, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, - 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, - 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85, 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, - 0xd6, 0xf0, 0xfe, 0xec, 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e, - 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01, 0xf4, 0xfe, 0xdd, 0x10, - 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee, 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, - 0x56, 0x12, 0x09, 0x1d, 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23, - 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09, 0x24, 0xfe, 0x12, 0x12, - 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42, 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, - 0xfe, 0x62, 0x08, 0x0a, 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43, - 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80, 0x13, 0x01, 0x0c, 0x06, - 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, - 0x4a, 0x13, 0x21, 0x6e, 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10, - 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49, 0x88, 0x20, 0x6e, 0x01, - 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, - 0x64, 0xfe, 0x05, 0xfa, 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe, - 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe, 0xe5, - 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, - 0x0c, 0x06, 0x54, 0xf9, 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50, - 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x68, 0x3b, - 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, - 0x50, 0x05, 0x73, 0x2e, 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25, - 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01, 0xa6, 0x23, 0x3f, 0x1b, - 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, - 0xfe, 0x8b, 0x55, 0xd9, 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01, - 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, - 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d, 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, - 0x3d, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08, - 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03, 0xb6, 0x1e, 0x83, 0x01, - 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45, 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, - 0xfe, 0xf8, 0x15, 0x01, 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82, - 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e, 0x05, 0x72, 0xfe, 0xc0, - 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, - 0x73, 0x01, 0xfe, 0x56, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd, - 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe, 0xe8, 0x14, 0x01, 0xa6, - 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe, 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, - 0x09, 0x82, 0x4e, 0x05, 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, - 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd, 0x09, - 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b, 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, - 0xb2, 0x0d, 0x1b, 0x3d, 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72, - 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0xc0, 0x19, 0x05, - 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17, 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, - 0x5f, 0x02, 0x8f, 0xfe, 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32, - 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0xfe, 0xff, - 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, - 0x23, 0x3f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, - 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e, 0x02, 0x13, 0x58, 0xff, - 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58, 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, - 0x5c, 0x0a, 0x6f, 0x01, 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54, - 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07, 0x7c, 0x3a, 0x0b, 0x0e, - 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a, 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, - 0xfe, 0x1b, 0xf7, 0x00, 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe, - 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77, 0x02, 0x01, 0xc6, 0xfe, - 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, - 0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe, - 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12, 0x48, 0xfe, 0x08, 0x17, - 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d, 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, - 0x1c, 0xb4, 0x90, 0x04, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55, - 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x1c, 0x63, 0x13, - 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16, 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, - 0x17, 0x0a, 0xfe, 0x64, 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60, - 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8, 0x00, 0x1c, 0x95, 0x13, - 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, - 0xfe, 0x56, 0xf0, 0xfe, 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b, - 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x49, - 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, - 0x4d, 0xf4, 0x00, 0xf7, 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13, - 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xbe, 0xfe, 0x03, - 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, - 0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9, - 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, - 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01, 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, - 0x31, 0xa2, 0x78, 0xf2, 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e, - 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10, 0xfe, 0x40, 0x5a, 0x23, - 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, - 0x18, 0x62, 0x80, 0xfe, 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe, - 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe, 0x43, 0x48, 0x2d, 0x93, - 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe, 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, - 0x04, 0xfe, 0x34, 0x10, 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0, - 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa, 0x18, 0x45, 0xfe, 0x1c, - 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, - 0x58, 0xfe, 0x40, 0xf4, 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01, - 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe, 0x7e, 0x01, 0xfe, 0xc8, - 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01, 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, - 0xfe, 0xc8, 0x44, 0x4e, 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14, - 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, - 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, - 0x01, 0x08, 0x17, 0xc1, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1, - 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01, 0x08, 0x02, 0x50, 0x02, - 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f, 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, - 0x17, 0x74, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe, - 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17, 0x74, 0x5f, 0xcc, 0x01, - 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c, 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, - 0x4d, 0x5f, 0xa1, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, - 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13, 0x16, 0xfe, 0x64, 0x1a, - 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09, 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, - 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, - 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa, 0xfe, 0x80, 0xe7, 0x1a, - 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe, 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, - 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80, - 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x0a, - 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c, 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, - 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3, - 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe, 0xf4, 0x1a, 0xfe, 0xfa, - 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, - 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07, - 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x24, 0xb1, 0xfe, - 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, - 0x1a, 0x87, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1, - 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe, 0xaf, 0x19, 0xfe, 0x98, - 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b, 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, - 0xfe, 0x30, 0x90, 0x04, 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04, - 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a, 0x7c, 0x12, 0xfe, 0x0f, - 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6, 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, - 0xfe, 0x96, 0x1b, 0x5c, 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe, - 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee, 0x1b, 0xfe, 0x36, 0x14, - 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, - 0xfe, 0x81, 0xe7, 0x1a, 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45, - 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe, 0x39, 0xf0, 0x75, 0x26, - 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13, 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, - 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13, - 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, - 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, - 0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01, - 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14, 0x56, - 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d, 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, - 0x00, 0x40, 0x8d, 0x30, 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80, - 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, - 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31, 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, - 0xb9, 0x02, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44, - 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09, 0x1a, 0xa4, 0x0a, 0x67, - 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89, 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, - 0x1d, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b, - 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10, 0xfe, 0x4e, 0xe4, 0xfe, - 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe, 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, - 0xfe, 0x96, 0x00, 0xd1, 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1, - 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, - 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa, 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, - 0xf0, 0xfe, 0xba, 0x1d, 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8, - 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe, 0x1a, 0x10, 0x09, 0x0d, - 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e, 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, - 0xfe, 0x04, 0xfe, 0x99, 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08, - 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e, 0xfe, 0x82, 0xf0, 0xfe, - 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, - 0x80, 0x04, 0xfe, 0x98, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82, - 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86, 0x83, 0x33, 0x0b, 0x0e, - 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, - 0x80, 0x04, 0xfe, 0x84, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80, - 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04, 0xfe, 0x99, 0x83, 0xfe, - 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, - 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, - 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x08, 0x90, 0x04, - 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, - 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, - 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x3c, 0x90, 0x04, - 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, - 0x33, 0x0b, 0x77, 0x0e, 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00, +static unsigned char _adv_asc38C1600_buf[] = { + 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0, + 0x18, 0xe4, 0x01, 0x00, + 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13, 0x2e, 0x1e, 0x02, 0x00, + 0x07, 0x17, 0xc0, 0x5f, + 0x00, 0xfa, 0xff, 0xff, 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, + 0x85, 0xf0, 0x86, 0xf0, + 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00, + 0x98, 0x57, 0x01, 0xe6, + 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4, 0x08, 0x00, 0xf0, 0x1d, + 0x38, 0x54, 0x32, 0xf0, + 0x10, 0x00, 0xc2, 0x0e, 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, + 0x00, 0xe6, 0xb1, 0xf0, + 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01, + 0x06, 0x13, 0x0c, 0x1c, + 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc, 0xbc, 0x0e, 0xa2, 0x12, + 0xb9, 0x54, 0x00, 0x80, + 0x62, 0x0a, 0x5a, 0x12, 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, + 0x03, 0xe6, 0x01, 0xea, + 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12, + 0x04, 0x13, 0xbb, 0x55, + 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4, 0x40, 0x00, 0xb6, 0x00, + 0xbb, 0x00, 0xc0, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, + 0x4c, 0x1c, 0x4e, 0x1c, + 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00, + 0x24, 0x01, 0x3c, 0x01, + 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, + 0x78, 0x01, 0x7c, 0x01, + 0xc6, 0x0e, 0x0c, 0x10, 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, + 0x6e, 0x1e, 0x02, 0x48, + 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7, + 0x03, 0xfc, 0x06, 0x00, + 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12, 0x18, 0x1a, 0x70, 0x1a, + 0x30, 0x1c, 0x38, 0x1c, + 0x10, 0x44, 0x00, 0x4c, 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, + 0x5d, 0xf0, 0xa7, 0xf0, + 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00, + 0x33, 0x00, 0x34, 0x00, + 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, + 0x79, 0x01, 0x3c, 0x09, + 0x68, 0x0d, 0x02, 0x10, 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, + 0x40, 0x16, 0x50, 0x16, + 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc, + 0x05, 0xf0, 0x09, 0xf0, + 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7, 0x0a, 0x00, 0x9b, 0x00, + 0x9c, 0x00, 0xa4, 0x00, + 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, + 0xe9, 0x09, 0x5c, 0x0c, + 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, + 0x42, 0x1d, 0x08, 0x44, + 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x89, 0x48, 0x68, 0x54, + 0x83, 0x55, 0x83, 0x59, + 0x31, 0xe4, 0x02, 0xe6, 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, + 0x4b, 0xf4, 0x04, 0xf8, + 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, + 0xa8, 0x00, 0xaa, 0x00, + 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01, 0x26, 0x01, 0x60, 0x01, + 0x7a, 0x01, 0x82, 0x01, + 0xc8, 0x01, 0xca, 0x01, 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, + 0x68, 0x08, 0x10, 0x0d, + 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10, + 0xf3, 0x10, 0x06, 0x12, + 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13, 0x10, 0x13, 0xfe, 0x9c, + 0xf0, 0x35, 0x05, 0xfe, + 0xec, 0x0e, 0xff, 0x10, 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, + 0xfe, 0x88, 0x01, 0xff, + 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00, + 0x00, 0xfe, 0x57, 0x24, + 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00, 0x00, 0x1a, 0xff, 0x09, + 0x00, 0x00, 0xff, 0x08, + 0x01, 0x01, 0xff, 0x08, 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, + 0xff, 0xff, 0xff, 0x13, + 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00, + 0xfe, 0x04, 0xf7, 0xe8, + 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe, 0x04, 0xf7, 0xe8, 0x7d, + 0x0d, 0x51, 0x37, 0xfe, + 0x3d, 0xf0, 0xfe, 0x0c, 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, + 0xfe, 0xf8, 0x01, 0xfe, + 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d, + 0x05, 0xfe, 0x08, 0x0f, + 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05, 0xfe, 0x0e, 0x03, 0xfe, + 0x28, 0x1c, 0x03, 0xfe, + 0xa6, 0x00, 0xfe, 0xd1, 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, + 0x48, 0xf0, 0xfe, 0x90, + 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8, + 0x02, 0xfe, 0x46, 0xf0, + 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60, 0x02, 0xfe, 0x43, 0xf0, + 0xfe, 0x4e, 0x02, 0xfe, + 0x44, 0xf0, 0xfe, 0x52, 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, + 0x0d, 0xa2, 0x1c, 0x07, + 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02, + 0x1c, 0xf5, 0xfe, 0x1e, + 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7, 0x10, 0xfe, 0x06, 0xfc, + 0xde, 0x0a, 0x81, 0x01, + 0xa3, 0x05, 0x35, 0x1f, 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, + 0x81, 0x01, 0x5c, 0xfe, + 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, + 0xfe, 0x58, 0x1c, 0x1c, + 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c, 0x02, + 0x2b, 0xfe, 0x9e, 0x02, + 0xfe, 0x5a, 0x1c, 0xfe, 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, + 0x00, 0x47, 0xb8, 0x01, + 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09, + 0x1a, 0x31, 0xfe, 0x69, + 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0x01, 0xfe, + 0x1e, 0x1e, 0x20, 0x2c, + 0xfe, 0x05, 0xf6, 0xde, 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, + 0x44, 0x15, 0x56, 0x51, + 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57, + 0x01, 0x18, 0x09, 0x00, + 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41, 0x58, 0x0a, 0xba, 0x01, + 0x18, 0xfe, 0xc8, 0x54, + 0x7b, 0xfe, 0x1c, 0x03, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, + 0xfe, 0x02, 0xe8, 0x30, + 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0, + 0xfe, 0xe4, 0x01, 0xfe, + 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40, 0x1c, 0x2a, 0xeb, 0xfe, + 0x26, 0xf0, 0xfe, 0x66, + 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, + 0xef, 0x10, 0xfe, 0x9f, + 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05, + 0x70, 0x37, 0xfe, 0x48, + 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x26, + 0x21, 0xb9, 0xc7, 0x20, + 0xb9, 0x0a, 0x57, 0x01, 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, + 0xe1, 0x2a, 0xeb, 0xfe, + 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32, + 0x15, 0xfe, 0xe4, 0x00, + 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe, 0xc6, 0x03, 0x01, 0x41, + 0xfe, 0x06, 0xf0, 0xfe, + 0xd6, 0x03, 0xaf, 0xa0, 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, + 0x03, 0x81, 0x1e, 0x1b, + 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05, + 0xea, 0xfe, 0x46, 0x1c, + 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, + 0xfe, 0x48, 0x1c, 0x75, + 0x01, 0xa6, 0x86, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, + 0xe1, 0x01, 0x18, 0x77, + 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42, + 0x8f, 0xfe, 0x70, 0x02, + 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29, 0x2f, 0xfe, 0x4e, 0x04, + 0x16, 0xfe, 0x4a, 0x04, + 0x7e, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, + 0x02, 0x00, 0x10, 0x01, + 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25, + 0xee, 0xfe, 0x4c, 0x44, + 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13, 0x34, 0xfe, 0x4c, 0x54, + 0x7b, 0xec, 0x60, 0x8d, + 0x30, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, + 0x0c, 0x06, 0x28, 0xfe, + 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10, + 0x13, 0x34, 0xfe, 0x4c, + 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x54, + 0x13, 0x01, 0x0c, 0x06, + 0x28, 0xa5, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, + 0x28, 0xf9, 0x1f, 0x7f, + 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f, + 0xfe, 0xa4, 0x0e, 0x05, + 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe, 0x1c, 0x90, 0x04, 0xfe, + 0x9c, 0x93, 0x3a, 0x0b, + 0x0e, 0x8b, 0x02, 0x1f, 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, + 0x7d, 0x1d, 0xfe, 0x46, + 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04, + 0xfe, 0x87, 0x83, 0xfe, + 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x98, + 0x13, 0x0f, 0xfe, 0x20, + 0x80, 0x04, 0xfe, 0xa0, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, + 0x12, 0x01, 0x38, 0x06, + 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda, + 0x05, 0xd0, 0x54, 0x01, + 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x1e, 0xfe, + 0x50, 0x12, 0x5e, 0xff, + 0x02, 0x00, 0x10, 0x2f, 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, + 0x00, 0x10, 0x2f, 0xfe, + 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01, + 0x38, 0xfe, 0x4a, 0xf0, + 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba, 0x05, 0x71, 0x2e, 0xfe, + 0x21, 0x00, 0xf1, 0x2e, + 0xfe, 0x22, 0x00, 0xa2, 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, + 0x10, 0x2f, 0xfe, 0xd0, + 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe, + 0x1c, 0x00, 0x4d, 0x01, + 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27, 0x01, 0x01, 0x0c, 0x06, + 0x28, 0xfe, 0x24, 0x12, + 0x3e, 0x01, 0x84, 0x1f, 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, + 0x0d, 0x00, 0x01, 0x42, + 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13, + 0x03, 0xb6, 0x1e, 0xfe, + 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13, 0x3e, 0x01, 0x84, 0x17, + 0xfe, 0x72, 0x06, 0x0a, + 0x07, 0x01, 0x38, 0x06, 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, + 0x19, 0x16, 0xfe, 0x68, + 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66, + 0x03, 0x9a, 0x1e, 0xfe, + 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13, 0x01, 0xc6, 0x09, 0x12, + 0x48, 0xfe, 0x92, 0x06, + 0x2e, 0x12, 0x01, 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, + 0x58, 0xff, 0x02, 0x00, + 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17, + 0xfe, 0xea, 0x06, 0x01, + 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01, 0xfe, 0x84, 0x19, 0x16, + 0xfe, 0xe0, 0x06, 0x15, + 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, + 0x01, 0x84, 0xfe, 0xae, + 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a, + 0x1e, 0xfe, 0x1a, 0x12, + 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe, + 0x43, 0x48, 0x62, 0x80, + 0xf0, 0x45, 0x0a, 0x95, 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, + 0x36, 0xfe, 0x02, 0xf6, + 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e, + 0xd0, 0x0d, 0x17, 0xfe, + 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe, 0x90, 0x07, 0x26, 0x20, + 0x9e, 0x15, 0x82, 0x01, + 0x41, 0x15, 0xe2, 0x21, 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, + 0x57, 0x10, 0xe6, 0x05, + 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84, + 0xfe, 0x9c, 0x32, 0x5f, + 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00, 0x2f, 0xed, 0x2a, 0x3c, + 0xfe, 0x0a, 0xf0, 0xfe, + 0xce, 0x07, 0xae, 0xfe, 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, + 0xaf, 0xa0, 0x05, 0x29, + 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14, + 0x00, 0x01, 0x08, 0x14, + 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, + 0x14, 0x00, 0x05, 0xfe, + 0xc6, 0x09, 0x01, 0x76, 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, + 0x12, 0xfe, 0x30, 0x13, + 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, + 0x01, 0x08, 0x14, 0x00, + 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00, 0x05, 0xef, 0x7c, 0x4a, + 0x78, 0x4f, 0x0f, 0xfe, + 0x9a, 0x81, 0x04, 0xfe, 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, + 0x28, 0x48, 0xfe, 0x6c, + 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32, + 0x12, 0x53, 0x63, 0x4e, + 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, + 0x6c, 0x08, 0xaf, 0xa0, + 0xae, 0xfe, 0x96, 0x08, 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, + 0x05, 0xed, 0xfe, 0x9c, + 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe, + 0x1e, 0xfe, 0x99, 0x58, + 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe, 0x16, 0x09, 0x10, 0x6a, + 0x22, 0x6b, 0x01, 0x0c, + 0x61, 0x54, 0x44, 0x21, 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, + 0x1e, 0x47, 0x2c, 0x7a, + 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40, + 0x01, 0x0c, 0x61, 0x65, + 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20, 0x6e, 0x01, 0xfe, 0x6a, + 0x16, 0xfe, 0x08, 0x50, + 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, + 0x01, 0xfe, 0xce, 0x1e, + 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e, + 0x01, 0xfe, 0xfe, 0x1e, + 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b, 0x22, 0x4c, 0xfe, 0x8a, + 0x10, 0x01, 0x0c, 0x06, + 0x54, 0xfe, 0x50, 0x12, 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, + 0x10, 0x6a, 0x22, 0x6b, + 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04, + 0xfe, 0x9f, 0x83, 0x33, + 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90, 0x04, 0xfe, 0xc4, 0x93, + 0x3a, 0x0b, 0xfe, 0xc6, + 0x90, 0x04, 0xfe, 0xc6, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, + 0x01, 0xfe, 0xce, 0x1e, + 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90, + 0x04, 0xfe, 0xc0, 0x93, + 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2, 0x93, 0x79, 0x0b, 0x0e, + 0x10, 0x4b, 0x22, 0x4c, + 0x10, 0x64, 0x22, 0x34, 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, + 0x4e, 0x11, 0x2f, 0xfe, + 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b, + 0x3c, 0x37, 0x88, 0xf5, + 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a, 0xd2, 0xfe, 0x1e, 0x0a, + 0xd3, 0xfe, 0x42, 0x0a, + 0xae, 0xfe, 0x12, 0x0a, 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, + 0x05, 0x29, 0x01, 0x41, + 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07, + 0xfe, 0x14, 0x12, 0x01, + 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x74, 0x12, 0xfe, + 0x2e, 0x1c, 0x05, 0xfe, + 0x1a, 0x0c, 0x01, 0x76, 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, + 0xfe, 0x2c, 0x1c, 0xfe, + 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe, + 0x92, 0x10, 0xc4, 0xf6, + 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe, 0x1a, 0x0c, 0xc5, 0xfe, + 0xe7, 0x10, 0xfe, 0x2b, + 0xf0, 0xbf, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, + 0xac, 0xfe, 0xd2, 0xf0, + 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07, + 0x1b, 0xbf, 0xd4, 0x5b, + 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5, 0xfe, 0xa9, 0x10, 0x75, + 0x5e, 0x32, 0x1f, 0x7f, + 0x01, 0x42, 0x19, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, + 0x05, 0x70, 0xfe, 0x74, + 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78, + 0x0f, 0x4d, 0x01, 0xfe, + 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05, 0x5b, 0x01, 0x0c, 0x06, + 0x0d, 0x2b, 0xfe, 0xe2, + 0x0b, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, + 0xfe, 0x88, 0x13, 0x21, + 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe, + 0x83, 0x83, 0xfe, 0xc9, + 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42, 0x13, 0x0f, 0xfe, 0x04, + 0x91, 0x04, 0xfe, 0x84, + 0x93, 0xfe, 0xca, 0x57, 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, + 0xfe, 0xcb, 0x57, 0x0b, + 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03, + 0x6a, 0x3b, 0x6b, 0x10, + 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01, 0xc2, 0xc8, 0x7a, 0x30, + 0x20, 0x6e, 0xdb, 0x64, + 0xdc, 0x34, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, + 0xfe, 0x04, 0xfa, 0x64, + 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97, + 0x10, 0x98, 0x91, 0x6c, + 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06, 0x24, 0x1b, 0x40, 0x91, + 0x4b, 0x7e, 0x4c, 0x01, + 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, + 0x58, 0xfe, 0x91, 0x58, + 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24, + 0x1b, 0x40, 0x01, 0x0c, + 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe, 0x8e, 0x1e, 0x4f, 0x0f, + 0xfe, 0x10, 0x90, 0x04, + 0xfe, 0x90, 0x93, 0x3a, 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, + 0x79, 0x0b, 0x0e, 0xfe, + 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb, + 0x01, 0x0c, 0x06, 0x0d, + 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e, 0xfe, 0x6e, 0x0a, 0xfe, + 0x0c, 0x58, 0xfe, 0x8d, + 0x58, 0x05, 0x5b, 0x26, 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, + 0x83, 0x33, 0x0b, 0x0e, + 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, + 0x19, 0xfe, 0x19, 0x41, + 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef, 0x1f, 0x92, 0x01, 0x42, + 0x19, 0xfe, 0x44, 0x00, + 0xfe, 0x90, 0x10, 0xfe, 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, + 0x4c, 0xfe, 0x0c, 0x51, + 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe, + 0x76, 0x10, 0xac, 0xfe, + 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x5d, 0x03, + 0xe3, 0x23, 0x07, 0xfe, + 0x08, 0x13, 0x19, 0xfe, 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, + 0xcc, 0x0c, 0x1f, 0x92, + 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2, + 0x0c, 0xfe, 0x3e, 0x10, + 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe, 0x22, 0x00, 0x05, 0x70, + 0xfe, 0xcb, 0xf0, 0xfe, + 0xea, 0x0c, 0x19, 0xfe, 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, + 0xf4, 0x0c, 0x19, 0x94, + 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3, + 0xfe, 0xcc, 0xf0, 0xef, + 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12, 0x00, 0x37, 0x13, 0xfe, + 0x4e, 0x11, 0x2f, 0xfe, + 0x16, 0x0d, 0xfe, 0x9e, 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, + 0x3c, 0x37, 0x88, 0xf5, + 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32, + 0x2f, 0xfe, 0x3e, 0x0d, + 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0, 0xd4, 0x9f, 0xd5, 0x9f, + 0xd2, 0x9f, 0xd3, 0x9f, + 0x05, 0x29, 0x01, 0x41, 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, + 0xc5, 0x75, 0xd7, 0x99, + 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8, + 0x9c, 0x2f, 0xfe, 0x8c, + 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01, 0x48, 0xa4, 0x19, 0xfe, + 0x42, 0x00, 0x05, 0x70, + 0x90, 0x07, 0xfe, 0x81, 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, + 0x0d, 0xfe, 0x44, 0x13, + 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b, + 0xfe, 0xda, 0x0e, 0x0a, + 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe, 0x28, 0x00, 0xfe, 0xfa, + 0x10, 0x01, 0xfe, 0xf4, + 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, + 0x15, 0x56, 0x01, 0x85, + 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe, + 0xcc, 0x10, 0x01, 0xa7, + 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f, 0xfe, 0x19, 0x82, 0x04, + 0xfe, 0x99, 0x83, 0xfe, + 0xcc, 0x47, 0x0b, 0x0e, 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, + 0x43, 0x00, 0xfe, 0xa2, + 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, + 0x00, 0x1d, 0x40, 0x15, + 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01, 0xfe, 0x9e, 0x1e, 0x05, + 0xfe, 0x3a, 0x03, 0x01, + 0x0c, 0x06, 0x0d, 0x5d, 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, + 0x76, 0x06, 0x12, 0xfe, + 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c, + 0xfe, 0x9d, 0xf0, 0xfe, + 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x94, 0x0e, 0x01, + 0x0c, 0x61, 0x12, 0x44, + 0xfe, 0x9f, 0x10, 0x19, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, + 0xfe, 0x2e, 0x10, 0x19, + 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19, + 0xfe, 0x41, 0x00, 0xa2, + 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75, 0x03, 0x81, 0x1e, 0x2b, + 0xea, 0x4f, 0xfe, 0x04, + 0xe6, 0x12, 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, + 0x35, 0xfe, 0x12, 0x1c, + 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01, + 0xfe, 0xd4, 0x11, 0x05, + 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e, 0x47, 0x46, 0x28, 0xfe, + 0xce, 0x45, 0x31, 0x51, + 0xfe, 0x06, 0xea, 0xe0, 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, + 0x67, 0xfe, 0x98, 0x56, + 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01, + 0x0c, 0x06, 0x28, 0xfe, + 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe, 0x41, 0x58, 0x0a, 0xba, + 0xfe, 0xfa, 0x14, 0xfe, + 0x49, 0x54, 0xb0, 0xfe, 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, + 0xfe, 0xe0, 0x14, 0xfe, + 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47, + 0xfe, 0xad, 0x13, 0x05, + 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12, 0x26, 0x20, 0x96, 0x20, + 0xe7, 0xfe, 0x08, 0x1c, + 0xfe, 0x7c, 0x19, 0xfe, 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, + 0x48, 0x55, 0xa5, 0x3b, + 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe, + 0xf0, 0x1a, 0x03, 0xfe, + 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe, 0x1e, 0x10, 0xfe, 0x02, + 0xec, 0xe7, 0x53, 0x00, + 0x36, 0xfe, 0x04, 0xec, 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, + 0x01, 0xfe, 0x62, 0x1b, + 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02, + 0xea, 0xe7, 0x53, 0x92, + 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3, 0xfe, 0x2a, 0x10, 0x03, + 0xfe, 0x38, 0x01, 0x23, + 0xfe, 0xf0, 0xff, 0x10, 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, + 0x01, 0x01, 0xfe, 0x1e, + 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02, + 0x26, 0x02, 0x21, 0x96, + 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13, 0x1f, 0x1d, 0x47, 0xb5, + 0xc3, 0xfe, 0xe1, 0x10, + 0xcf, 0xfe, 0x03, 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, + 0xfe, 0x03, 0xdc, 0xfe, + 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe, + 0x00, 0xcc, 0x02, 0xfe, + 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, + 0x0f, 0xfe, 0x1c, 0x80, + 0x04, 0xfe, 0x9c, 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, + 0x0f, 0xfe, 0x1e, 0x80, + 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe, + 0x1d, 0x80, 0x04, 0xfe, + 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c, 0x13, 0x01, 0xfe, 0xee, + 0x1e, 0xac, 0xfe, 0x14, + 0x13, 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, + 0x1f, 0xfe, 0x30, 0xf4, + 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09, + 0x56, 0xfb, 0x01, 0xfe, + 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01, 0xfe, 0xf4, 0x1c, 0x01, + 0xfe, 0x00, 0x1d, 0x15, + 0xfe, 0xe9, 0x00, 0x01, 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, + 0x22, 0x1b, 0xfe, 0x1e, + 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe, + 0x96, 0x90, 0x04, 0xfe, + 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64, 0x01, 0x22, 0xfe, 0x66, + 0x01, 0x01, 0x0c, 0x06, + 0x65, 0xf9, 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, + 0x0e, 0x77, 0xfe, 0x01, + 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40, + 0x21, 0x2c, 0xfe, 0x00, + 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, + 0x06, 0x58, 0x03, 0xfe, + 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, + 0x03, 0xfe, 0xb2, 0x00, + 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10, + 0x66, 0x10, 0x55, 0x10, + 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe, 0x90, 0x4d, 0xfe, 0x91, + 0x54, 0x2b, 0xfe, 0x88, + 0x11, 0x46, 0x1a, 0x13, 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, + 0x91, 0x54, 0x2b, 0xfe, + 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe, + 0x00, 0x40, 0x8d, 0x2c, + 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xb2, 0x11, 0xfe, + 0x12, 0x1c, 0x75, 0xfe, + 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, + 0x14, 0xfe, 0x0e, 0x47, + 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01, + 0xa7, 0x90, 0x34, 0x60, + 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0xfe, 0x02, 0x80, + 0x09, 0x56, 0xfe, 0x34, + 0x13, 0x0a, 0x5a, 0x01, 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, + 0xfe, 0x45, 0x48, 0x01, + 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89, + 0x09, 0x1a, 0xa5, 0x0a, + 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85, 0xf2, 0x09, 0x9b, 0xa4, + 0xfe, 0x14, 0x56, 0xfe, + 0xd6, 0xf0, 0xfe, 0xec, 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, + 0xec, 0xb8, 0xfe, 0x9e, + 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01, + 0xf4, 0xfe, 0xdd, 0x10, + 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee, 0x09, 0x12, 0xfe, 0x48, + 0x12, 0x09, 0x0d, 0xfe, + 0x56, 0x12, 0x09, 0x1d, 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, + 0x13, 0x09, 0xfe, 0x23, + 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09, + 0x24, 0xfe, 0x12, 0x12, + 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42, 0xa1, 0x32, 0x01, 0x08, + 0xae, 0x41, 0x02, 0x32, + 0xfe, 0x62, 0x08, 0x0a, 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, + 0x35, 0x32, 0x01, 0x43, + 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80, + 0x13, 0x01, 0x0c, 0x06, + 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x44, 0x55, 0xfe, + 0xe5, 0x55, 0xb0, 0xfe, + 0x4a, 0x13, 0x21, 0x6e, 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, + 0xfe, 0xb6, 0x0e, 0x10, + 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49, + 0x88, 0x20, 0x6e, 0x01, + 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe, 0x04, 0x55, 0xfe, 0xa5, + 0x55, 0xfe, 0x04, 0xfa, + 0x64, 0xfe, 0x05, 0xfa, 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, + 0xfe, 0x40, 0x56, 0xfe, + 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe, + 0x44, 0x55, 0xfe, 0xe5, + 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x10, + 0x68, 0x22, 0x69, 0x01, + 0x0c, 0x06, 0x54, 0xf9, 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, + 0x6b, 0xfe, 0x2c, 0x50, + 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6, + 0x50, 0x03, 0x68, 0x3b, + 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03, 0x4b, 0x3b, 0x4c, 0xfe, + 0x40, 0x50, 0xfe, 0xc2, + 0x50, 0x05, 0x73, 0x2e, 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, + 0x16, 0x3d, 0x27, 0x25, + 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01, + 0xa6, 0x23, 0x3f, 0x1b, + 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13, 0x91, 0x4b, 0x7e, 0x4c, + 0xfe, 0x0a, 0x55, 0x31, + 0xfe, 0x8b, 0x55, 0xd9, 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, + 0x51, 0x05, 0x72, 0x01, + 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08, + 0x2a, 0x3c, 0x16, 0xc0, + 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d, 0x83, 0x2d, 0x7f, 0x1b, + 0xfe, 0x66, 0x15, 0x05, + 0x3d, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, + 0x2b, 0x3d, 0x01, 0x08, + 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03, + 0xb6, 0x1e, 0x83, 0x01, + 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45, 0x2d, 0x00, 0xa4, 0x46, + 0x07, 0x90, 0x3f, 0x01, + 0xfe, 0xf8, 0x15, 0x01, 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, + 0x01, 0x43, 0x09, 0x82, + 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e, + 0x05, 0x72, 0xfe, 0xc0, + 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66, 0x8a, 0x10, 0x66, 0x5e, + 0x32, 0x01, 0x08, 0x17, + 0x73, 0x01, 0xfe, 0x56, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, + 0x3d, 0x27, 0x25, 0xbd, + 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe, + 0xe8, 0x14, 0x01, 0xa6, + 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe, 0x4a, 0xf4, 0x07, 0xfe, + 0x0e, 0x12, 0x01, 0x43, + 0x09, 0x82, 0x4e, 0x05, 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, + 0x01, 0x08, 0x17, 0x73, + 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, + 0x27, 0x25, 0xbd, 0x09, + 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b, 0xfe, 0xaa, 0x14, 0xfe, + 0xb6, 0x14, 0x86, 0xa8, + 0xb2, 0x0d, 0x1b, 0x3d, 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, + 0x82, 0x4e, 0x05, 0x72, + 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, + 0xfe, 0xc0, 0x19, 0x05, + 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17, 0xfe, 0xe2, 0x15, 0x5f, + 0xcc, 0x01, 0x08, 0x26, + 0x5f, 0x02, 0x8f, 0xfe, 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, + 0xcc, 0x15, 0x5e, 0x32, + 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, + 0xad, 0x23, 0xfe, 0xff, + 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, + 0x00, 0x57, 0x52, 0xad, + 0x23, 0x3f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, + 0x02, 0x00, 0x57, 0x52, + 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e, + 0x02, 0x13, 0x58, 0xff, + 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58, 0x02, 0x0a, 0x66, 0x01, + 0x5c, 0x0a, 0x55, 0x01, + 0x5c, 0x0a, 0x6f, 0x01, 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, + 0xff, 0x03, 0x00, 0x54, + 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07, + 0x7c, 0x3a, 0x0b, 0x0e, + 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a, 0x19, 0xfe, 0xfb, 0x19, + 0xfe, 0x1a, 0xf7, 0x00, + 0xfe, 0x1b, 0xf7, 0x00, 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, + 0xda, 0x6d, 0x02, 0xfe, + 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77, + 0x02, 0x01, 0xc6, 0xfe, + 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17, 0x27, + 0x25, 0xbe, 0x01, 0x08, + 0x16, 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, + 0x03, 0x9a, 0x1e, 0xfe, + 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12, + 0x48, 0xfe, 0x08, 0x17, + 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d, 0xb4, 0x7b, 0xfe, 0x26, + 0x17, 0x4d, 0x13, 0x07, + 0x1c, 0xb4, 0x90, 0x04, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, + 0xff, 0x02, 0x83, 0x55, + 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80, + 0x17, 0x1c, 0x63, 0x13, + 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16, 0x13, 0xd6, 0xfe, 0x64, + 0x00, 0xb0, 0xfe, 0x80, + 0x17, 0x0a, 0xfe, 0x64, 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, + 0x53, 0x07, 0xfe, 0x60, + 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8, + 0x00, 0x1c, 0x95, 0x13, + 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0x8c, 0x17, 0x45, 0xf3, + 0xfe, 0x43, 0xf4, 0x96, + 0xfe, 0x56, 0xf0, 0xfe, 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, + 0xf4, 0x94, 0xf6, 0x8b, + 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe, + 0xda, 0x17, 0x62, 0x49, + 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe, 0xda, 0x17, 0x62, 0x80, + 0x71, 0x50, 0x26, 0xfe, + 0x4d, 0xf4, 0x00, 0xf7, 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, + 0x58, 0x02, 0x50, 0x13, + 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27, + 0x25, 0xbe, 0xfe, 0x03, + 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe9, + 0x0a, 0x01, 0x08, 0x16, + 0xa9, 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, + 0x01, 0x08, 0x16, 0xa9, + 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01, + 0x08, 0x16, 0xa9, 0x27, + 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01, 0x03, 0xb6, 0x1e, 0x83, + 0x01, 0x38, 0x06, 0x24, + 0x31, 0xa2, 0x78, 0xf2, 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, + 0x78, 0x03, 0x9a, 0x1e, + 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10, + 0xfe, 0x40, 0x5a, 0x23, + 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x49, 0x71, 0x8c, + 0x80, 0x48, 0xfe, 0xaa, + 0x18, 0x62, 0x80, 0xfe, 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, + 0xfe, 0xac, 0x1d, 0xfe, + 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe, + 0x43, 0x48, 0x2d, 0x93, + 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe, 0x40, 0x10, 0x2d, 0xb4, + 0x36, 0xfe, 0x34, 0xf4, + 0x04, 0xfe, 0x34, 0x10, 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, + 0x28, 0x10, 0xfe, 0xc0, + 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa, + 0x18, 0x45, 0xfe, 0x1c, + 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe, 0x0c, + 0x19, 0xfe, 0x04, 0xf4, + 0x58, 0xfe, 0x40, 0xf4, 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, + 0x21, 0xfe, 0x7f, 0x01, + 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe, + 0x7e, 0x01, 0xfe, 0xc8, + 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01, 0xfe, 0x48, 0x45, 0xfa, + 0x21, 0xfe, 0x81, 0x01, + 0xfe, 0xc8, 0x44, 0x4e, 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, + 0x13, 0x0d, 0x02, 0x14, + 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17, + 0xfe, 0x82, 0x19, 0x14, + 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f, 0xfe, 0x89, 0x49, 0x01, + 0x08, 0x02, 0x14, 0x07, + 0x01, 0x08, 0x17, 0xc1, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, + 0x01, 0x08, 0x17, 0xc1, + 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01, + 0x08, 0x02, 0x50, 0x02, + 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f, 0x01, 0x08, 0x17, 0x74, + 0x14, 0x12, 0x01, 0x08, + 0x17, 0x74, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, + 0x08, 0x17, 0x74, 0xfe, + 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17, + 0x74, 0x5f, 0xcc, 0x01, + 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c, 0x13, 0xc8, 0x20, 0xe4, + 0xfe, 0x49, 0xf4, 0x00, + 0x4d, 0x5f, 0xa1, 0x5e, 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, + 0x02, 0x00, 0x10, 0x2f, + 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13, + 0x16, 0xfe, 0x64, 0x1a, + 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09, 0x07, 0x5d, 0x01, 0x0c, + 0x61, 0x07, 0x44, 0x02, + 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, + 0x13, 0x0a, 0x9d, 0x01, + 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa, + 0xfe, 0x80, 0xe7, 0x1a, + 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe, 0xb2, 0x16, 0xaa, 0x02, + 0x0a, 0x5a, 0x01, 0x18, + 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, + 0x7e, 0x1e, 0xfe, 0x80, + 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18, + 0xfe, 0x80, 0x4c, 0x0a, + 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c, 0xe5, 0xfe, 0x18, 0xdf, + 0xfe, 0x19, 0xde, 0xfe, + 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, + 0x2a, 0x1c, 0xfa, 0xb3, + 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe, + 0xf4, 0x1a, 0xfe, 0xfa, + 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x24, + 0xfe, 0x18, 0x58, 0x03, + 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, + 0xfe, 0x30, 0xf4, 0x07, + 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, + 0xf7, 0x24, 0xb1, 0xfe, + 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x26, 0x1b, + 0xfe, 0xba, 0x10, 0x1c, + 0x1a, 0x87, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, + 0x1d, 0xf7, 0x54, 0xb1, + 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe, + 0xaf, 0x19, 0xfe, 0x98, + 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b, 0xfe, 0x8a, 0x10, 0x1c, + 0x1a, 0x87, 0x8b, 0x0f, + 0xfe, 0x30, 0x90, 0x04, 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, + 0xfe, 0x32, 0x90, 0x04, + 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a, + 0x7c, 0x12, 0xfe, 0x0f, + 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6, 0x1b, 0xfe, 0x5e, 0x14, + 0x31, 0x02, 0xc9, 0x2b, + 0xfe, 0x96, 0x1b, 0x5c, 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, + 0x6a, 0xfe, 0x19, 0xfe, + 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee, + 0x1b, 0xfe, 0x36, 0x14, + 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, + 0xfe, 0x80, 0xe7, 0x1a, + 0xfe, 0x81, 0xe7, 0x1a, 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, + 0x30, 0xfe, 0x12, 0x45, + 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe, + 0x39, 0xf0, 0x75, 0x26, + 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13, 0x11, 0x02, 0x87, 0x03, + 0xe3, 0x23, 0x07, 0xfe, + 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, + 0x56, 0xfe, 0x3c, 0x13, + 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a, + 0x01, 0x18, 0xcb, 0xfe, + 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xfe, 0xb2, 0x16, + 0xfe, 0x00, 0xcc, 0xcb, + 0xfe, 0xf3, 0x13, 0x3f, 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, + 0xfe, 0x80, 0x4c, 0x01, + 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24, + 0x12, 0xfe, 0x14, 0x56, + 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d, 0x02, 0xfe, 0x9c, 0xe7, + 0x0d, 0x19, 0xfe, 0x15, + 0x00, 0x40, 0x8d, 0x30, 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, + 0x83, 0xfe, 0x18, 0x80, + 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38, + 0x90, 0xfe, 0xba, 0x90, + 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31, 0xfe, 0xc9, 0x55, 0x02, + 0x21, 0xb9, 0x88, 0x20, + 0xb9, 0x02, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, + 0x18, 0xfe, 0x49, 0x44, + 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09, + 0x1a, 0xa4, 0x0a, 0x67, + 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89, 0x02, 0xfe, 0x4e, 0xe4, + 0x1d, 0x7b, 0xfe, 0x52, + 0x1d, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, + 0x4e, 0xe4, 0xdd, 0x7b, + 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10, + 0xfe, 0x4e, 0xe4, 0xfe, + 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe, 0x94, 0x00, 0xd1, 0x24, + 0xfe, 0x08, 0x10, 0x03, + 0xfe, 0x96, 0x00, 0xd1, 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, + 0x68, 0x54, 0xfe, 0xf1, + 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, + 0xfe, 0x1a, 0xf4, 0xfe, + 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa, 0x1d, 0x13, 0x1d, 0x02, + 0x09, 0x92, 0xfe, 0x5a, + 0xf0, 0xfe, 0xba, 0x1d, 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, + 0x5a, 0xf0, 0xfe, 0xc8, + 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe, + 0x1a, 0x10, 0x09, 0x0d, + 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e, 0x95, 0xa1, 0xc8, 0x02, + 0x1f, 0x93, 0x01, 0x42, + 0xfe, 0x04, 0xfe, 0x99, 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, + 0xfe, 0x14, 0xf0, 0x08, + 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e, + 0xfe, 0x82, 0xf0, 0xfe, + 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80, 0x83, 0x33, 0x0b, 0x0e, + 0x02, 0x0f, 0xfe, 0x18, + 0x80, 0x04, 0xfe, 0x98, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, + 0x80, 0x04, 0xfe, 0x82, + 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86, + 0x83, 0x33, 0x0b, 0x0e, + 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b, 0x83, 0x33, 0x0b, 0x0e, + 0x02, 0x0f, 0xfe, 0x04, + 0x80, 0x04, 0xfe, 0x84, 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, + 0x80, 0x04, 0xfe, 0x80, + 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04, + 0xfe, 0x99, 0x83, 0xfe, + 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x83, 0x04, 0xfe, 0x86, + 0x83, 0xfe, 0xce, 0x47, + 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, + 0x0b, 0x0e, 0x02, 0x0f, + 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f, + 0xfe, 0x08, 0x90, 0x04, + 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x8a, 0x90, 0x04, + 0xfe, 0x8a, 0x93, 0x79, + 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, + 0x0b, 0x0e, 0x02, 0x0f, + 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f, + 0xfe, 0x3c, 0x90, 0x04, + 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b, 0x0f, 0xfe, 0x03, 0x80, + 0x04, 0xfe, 0x83, 0x83, + 0x33, 0x0b, 0x77, 0x0e, 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00, }; -STATIC unsigned short _adv_asc38C1600_size = - sizeof(_adv_asc38C1600_buf); /* 0x1673 */ -STATIC ADV_DCNT _adv_asc38C1600_chksum = - 0x0604EF77UL; /* Expanded little-endian checksum. */ +static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */ +static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */ /* a_init.c */ /* @@ -14049,340 +13847,340 @@ STATIC ADV_DCNT _adv_asc38C1600_chksum = * on big-endian platforms so char fields read as words are actually being * unswapped on big-endian platforms. */ -STATIC ADVEEP_3550_CONFIG -Default_3550_EEPROM_Config __initdata = { - ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ - 0x0000, /* cfg_msw */ - 0xFFFF, /* disc_enable */ - 0xFFFF, /* wdtr_able */ - 0xFFFF, /* sdtr_able */ - 0xFFFF, /* start_motor */ - 0xFFFF, /* tagqng_able */ - 0xFFFF, /* bios_scan */ - 0, /* scam_tolerant */ - 7, /* adapter_scsi_id */ - 0, /* bios_boot_delay */ - 3, /* scsi_reset_delay */ - 0, /* bios_id_lun */ - 0, /* termination */ - 0, /* reserved1 */ - 0xFFE7, /* bios_ctrl */ - 0xFFFF, /* ultra_able */ - 0, /* reserved2 */ - ASC_DEF_MAX_HOST_QNG, /* max_host_qng */ - ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ - 0, /* dvc_cntl */ - 0, /* bug_fix */ - 0, /* serial_number_word1 */ - 0, /* serial_number_word2 */ - 0, /* serial_number_word3 */ - 0, /* check_sum */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* oem_name[16] */ - 0, /* dvc_err_code */ - 0, /* adv_err_code */ - 0, /* adv_err_addr */ - 0, /* saved_dvc_err_code */ - 0, /* saved_adv_err_code */ - 0, /* saved_adv_err_addr */ - 0 /* num_of_err */ +static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __initdata = { + ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ + 0x0000, /* cfg_msw */ + 0xFFFF, /* disc_enable */ + 0xFFFF, /* wdtr_able */ + 0xFFFF, /* sdtr_able */ + 0xFFFF, /* start_motor */ + 0xFFFF, /* tagqng_able */ + 0xFFFF, /* bios_scan */ + 0, /* scam_tolerant */ + 7, /* adapter_scsi_id */ + 0, /* bios_boot_delay */ + 3, /* scsi_reset_delay */ + 0, /* bios_id_lun */ + 0, /* termination */ + 0, /* reserved1 */ + 0xFFE7, /* bios_ctrl */ + 0xFFFF, /* ultra_able */ + 0, /* reserved2 */ + ASC_DEF_MAX_HOST_QNG, /* max_host_qng */ + ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ + 0, /* dvc_cntl */ + 0, /* bug_fix */ + 0, /* serial_number_word1 */ + 0, /* serial_number_word2 */ + 0, /* serial_number_word3 */ + 0, /* check_sum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , /* oem_name[16] */ + 0, /* dvc_err_code */ + 0, /* adv_err_code */ + 0, /* adv_err_addr */ + 0, /* saved_dvc_err_code */ + 0, /* saved_adv_err_code */ + 0, /* saved_adv_err_addr */ + 0 /* num_of_err */ }; -STATIC ADVEEP_3550_CONFIG -ADVEEP_3550_Config_Field_IsChar __initdata = { - 0, /* cfg_lsw */ - 0, /* cfg_msw */ - 0, /* -disc_enable */ - 0, /* wdtr_able */ - 0, /* sdtr_able */ - 0, /* start_motor */ - 0, /* tagqng_able */ - 0, /* bios_scan */ - 0, /* scam_tolerant */ - 1, /* adapter_scsi_id */ - 1, /* bios_boot_delay */ - 1, /* scsi_reset_delay */ - 1, /* bios_id_lun */ - 1, /* termination */ - 1, /* reserved1 */ - 0, /* bios_ctrl */ - 0, /* ultra_able */ - 0, /* reserved2 */ - 1, /* max_host_qng */ - 1, /* max_dvc_qng */ - 0, /* dvc_cntl */ - 0, /* bug_fix */ - 0, /* serial_number_word1 */ - 0, /* serial_number_word2 */ - 0, /* serial_number_word3 */ - 0, /* check_sum */ - { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, /* oem_name[16] */ - 0, /* dvc_err_code */ - 0, /* adv_err_code */ - 0, /* adv_err_addr */ - 0, /* saved_dvc_err_code */ - 0, /* saved_adv_err_code */ - 0, /* saved_adv_err_addr */ - 0 /* num_of_err */ +static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __initdata = { + 0, /* cfg_lsw */ + 0, /* cfg_msw */ + 0, /* -disc_enable */ + 0, /* wdtr_able */ + 0, /* sdtr_able */ + 0, /* start_motor */ + 0, /* tagqng_able */ + 0, /* bios_scan */ + 0, /* scam_tolerant */ + 1, /* adapter_scsi_id */ + 1, /* bios_boot_delay */ + 1, /* scsi_reset_delay */ + 1, /* bios_id_lun */ + 1, /* termination */ + 1, /* reserved1 */ + 0, /* bios_ctrl */ + 0, /* ultra_able */ + 0, /* reserved2 */ + 1, /* max_host_qng */ + 1, /* max_dvc_qng */ + 0, /* dvc_cntl */ + 0, /* bug_fix */ + 0, /* serial_number_word1 */ + 0, /* serial_number_word2 */ + 0, /* serial_number_word3 */ + 0, /* check_sum */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , /* oem_name[16] */ + 0, /* dvc_err_code */ + 0, /* adv_err_code */ + 0, /* adv_err_addr */ + 0, /* saved_dvc_err_code */ + 0, /* saved_adv_err_code */ + 0, /* saved_adv_err_addr */ + 0 /* num_of_err */ }; -STATIC ADVEEP_38C0800_CONFIG -Default_38C0800_EEPROM_Config __initdata = { - ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ - 0x0000, /* 01 cfg_msw */ - 0xFFFF, /* 02 disc_enable */ - 0xFFFF, /* 03 wdtr_able */ - 0x4444, /* 04 sdtr_speed1 */ - 0xFFFF, /* 05 start_motor */ - 0xFFFF, /* 06 tagqng_able */ - 0xFFFF, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 7, /* 09 adapter_scsi_id */ - 0, /* bios_boot_delay */ - 3, /* 10 scsi_reset_delay */ - 0, /* bios_id_lun */ - 0, /* 11 termination_se */ - 0, /* termination_lvd */ - 0xFFE7, /* 12 bios_ctrl */ - 0x4444, /* 13 sdtr_speed2 */ - 0x4444, /* 14 sdtr_speed3 */ - ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ - ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0x4444, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - PCI_VENDOR_ID_ASP, /* 58 subsysvid */ - PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __initdata = { + ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ + 0x0000, /* 01 cfg_msw */ + 0xFFFF, /* 02 disc_enable */ + 0xFFFF, /* 03 wdtr_able */ + 0x4444, /* 04 sdtr_speed1 */ + 0xFFFF, /* 05 start_motor */ + 0xFFFF, /* 06 tagqng_able */ + 0xFFFF, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 7, /* 09 adapter_scsi_id */ + 0, /* bios_boot_delay */ + 3, /* 10 scsi_reset_delay */ + 0, /* bios_id_lun */ + 0, /* 11 termination_se */ + 0, /* termination_lvd */ + 0xFFE7, /* 12 bios_ctrl */ + 0x4444, /* 13 sdtr_speed2 */ + 0x4444, /* 14 sdtr_speed3 */ + ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ + ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0x4444, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + PCI_VENDOR_ID_ASP, /* 58 subsysvid */ + PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ }; -STATIC ADVEEP_38C0800_CONFIG -ADVEEP_38C0800_Config_Field_IsChar __initdata = { - 0, /* 00 cfg_lsw */ - 0, /* 01 cfg_msw */ - 0, /* 02 disc_enable */ - 0, /* 03 wdtr_able */ - 0, /* 04 sdtr_speed1 */ - 0, /* 05 start_motor */ - 0, /* 06 tagqng_able */ - 0, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 1, /* 09 adapter_scsi_id */ - 1, /* bios_boot_delay */ - 1, /* 10 scsi_reset_delay */ - 1, /* bios_id_lun */ - 1, /* 11 termination_se */ - 1, /* termination_lvd */ - 0, /* 12 bios_ctrl */ - 0, /* 13 sdtr_speed2 */ - 0, /* 14 sdtr_speed3 */ - 1, /* 15 max_host_qng */ - 1, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - 0, /* 58 subsysvid */ - 0, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __initdata = { + 0, /* 00 cfg_lsw */ + 0, /* 01 cfg_msw */ + 0, /* 02 disc_enable */ + 0, /* 03 wdtr_able */ + 0, /* 04 sdtr_speed1 */ + 0, /* 05 start_motor */ + 0, /* 06 tagqng_able */ + 0, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 1, /* 09 adapter_scsi_id */ + 1, /* bios_boot_delay */ + 1, /* 10 scsi_reset_delay */ + 1, /* bios_id_lun */ + 1, /* 11 termination_se */ + 1, /* termination_lvd */ + 0, /* 12 bios_ctrl */ + 0, /* 13 sdtr_speed2 */ + 0, /* 14 sdtr_speed3 */ + 1, /* 15 max_host_qng */ + 1, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + 0, /* 58 subsysvid */ + 0, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ }; -STATIC ADVEEP_38C1600_CONFIG -Default_38C1600_EEPROM_Config __initdata = { - ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ - 0x0000, /* 01 cfg_msw */ - 0xFFFF, /* 02 disc_enable */ - 0xFFFF, /* 03 wdtr_able */ - 0x5555, /* 04 sdtr_speed1 */ - 0xFFFF, /* 05 start_motor */ - 0xFFFF, /* 06 tagqng_able */ - 0xFFFF, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 7, /* 09 adapter_scsi_id */ - 0, /* bios_boot_delay */ - 3, /* 10 scsi_reset_delay */ - 0, /* bios_id_lun */ - 0, /* 11 termination_se */ - 0, /* termination_lvd */ - 0xFFE7, /* 12 bios_ctrl */ - 0x5555, /* 13 sdtr_speed2 */ - 0x5555, /* 14 sdtr_speed3 */ - ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ - ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0x5555, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - PCI_VENDOR_ID_ASP, /* 58 subsysvid */ - PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __initdata = { + ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ + 0x0000, /* 01 cfg_msw */ + 0xFFFF, /* 02 disc_enable */ + 0xFFFF, /* 03 wdtr_able */ + 0x5555, /* 04 sdtr_speed1 */ + 0xFFFF, /* 05 start_motor */ + 0xFFFF, /* 06 tagqng_able */ + 0xFFFF, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 7, /* 09 adapter_scsi_id */ + 0, /* bios_boot_delay */ + 3, /* 10 scsi_reset_delay */ + 0, /* bios_id_lun */ + 0, /* 11 termination_se */ + 0, /* termination_lvd */ + 0xFFE7, /* 12 bios_ctrl */ + 0x5555, /* 13 sdtr_speed2 */ + 0x5555, /* 14 sdtr_speed3 */ + ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ + ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0x5555, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + PCI_VENDOR_ID_ASP, /* 58 subsysvid */ + PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ }; -STATIC ADVEEP_38C1600_CONFIG -ADVEEP_38C1600_Config_Field_IsChar __initdata = { - 0, /* 00 cfg_lsw */ - 0, /* 01 cfg_msw */ - 0, /* 02 disc_enable */ - 0, /* 03 wdtr_able */ - 0, /* 04 sdtr_speed1 */ - 0, /* 05 start_motor */ - 0, /* 06 tagqng_able */ - 0, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 1, /* 09 adapter_scsi_id */ - 1, /* bios_boot_delay */ - 1, /* 10 scsi_reset_delay */ - 1, /* bios_id_lun */ - 1, /* 11 termination_se */ - 1, /* termination_lvd */ - 0, /* 12 bios_ctrl */ - 0, /* 13 sdtr_speed2 */ - 0, /* 14 sdtr_speed3 */ - 1, /* 15 max_host_qng */ - 1, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }, /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - 0, /* 58 subsysvid */ - 0, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __initdata = { + 0, /* 00 cfg_lsw */ + 0, /* 01 cfg_msw */ + 0, /* 02 disc_enable */ + 0, /* 03 wdtr_able */ + 0, /* 04 sdtr_speed1 */ + 0, /* 05 start_motor */ + 0, /* 06 tagqng_able */ + 0, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 1, /* 09 adapter_scsi_id */ + 1, /* bios_boot_delay */ + 1, /* 10 scsi_reset_delay */ + 1, /* bios_id_lun */ + 1, /* 11 termination_se */ + 1, /* termination_lvd */ + 0, /* 12 bios_ctrl */ + 0, /* 13 sdtr_speed2 */ + 0, /* 14 sdtr_speed3 */ + 1, /* 15 max_host_qng */ + 1, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + 0, /* 58 subsysvid */ + 0, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ }; /* @@ -14393,136 +14191,128 @@ ADVEEP_38C1600_Config_Field_IsChar __initdata = { * For a non-fatal error return a warning code. If there are no warnings * then 0 is returned. */ -STATIC int __init -AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) +static int __init AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) { - ushort warn_code; - AdvPortAddr iop_base; - uchar pci_cmd_reg; - int status; - - warn_code = 0; - asc_dvc->err_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * PCI Command Register - * - * Note: AscPCICmdRegBits_BusMastering definition (0x0007) includes - * I/O Space Control, Memory Space Control and Bus Master Control bits. - */ - - if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister)) - & AscPCICmdRegBits_BusMastering) - != AscPCICmdRegBits_BusMastering) - { - pci_cmd_reg |= AscPCICmdRegBits_BusMastering; - - DvcAdvWritePCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister, pci_cmd_reg); - - if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)) - & AscPCICmdRegBits_BusMastering) - != AscPCICmdRegBits_BusMastering) - { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - - /* - * PCI Latency Timer - * - * If the "latency timer" register is 0x20 or above, then we don't need - * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it - * comes up less than 0x20). - */ - if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) { - DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, 0x20); - if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) - { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - - /* - * Save the state of the PCI Configuration Command Register - * "Parity Error Response Control" Bit. If the bit is clear (0), - * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore - * DMA parity errors. - */ - asc_dvc->cfg->control_flag = 0; - if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister) - & AscPCICmdRegBits_ParErrRespCtrl)) == 0) - { - asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR; - } + ushort warn_code; + AdvPortAddr iop_base; + uchar pci_cmd_reg; + int status; + + warn_code = 0; + asc_dvc->err_code = 0; + iop_base = asc_dvc->iop_base; + + /* + * PCI Command Register + * + * Note: AscPCICmdRegBits_BusMastering definition (0x0007) includes + * I/O Space Control, Memory Space Control and Bus Master Control bits. + */ + + if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister)) + & AscPCICmdRegBits_BusMastering) + != AscPCICmdRegBits_BusMastering) { + pci_cmd_reg |= AscPCICmdRegBits_BusMastering; + + DvcAdvWritePCIConfigByte(asc_dvc, + AscPCIConfigCommandRegister, + pci_cmd_reg); + + if (((DvcAdvReadPCIConfigByte + (asc_dvc, AscPCIConfigCommandRegister)) + & AscPCICmdRegBits_BusMastering) + != AscPCICmdRegBits_BusMastering) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } - asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) | - ADV_LIB_VERSION_MINOR; - asc_dvc->cfg->chip_version = - AdvGetChipVersion(iop_base, asc_dvc->bus_type); + /* + * PCI Latency Timer + * + * If the "latency timer" register is 0x20 or above, then we don't need + * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it + * comes up less than 0x20). + */ + if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) { + DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, + 0x20); + if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < + 0x20) { + warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; + } + } - ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n", - (ushort) AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1), - (ushort) ADV_CHIP_ID_BYTE); + /* + * Save the state of the PCI Configuration Command Register + * "Parity Error Response Control" Bit. If the bit is clear (0), + * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore + * DMA parity errors. + */ + asc_dvc->cfg->control_flag = 0; + if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister) + & AscPCICmdRegBits_ParErrRespCtrl)) == 0) { + asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR; + } - ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n", - (ushort) AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0), - (ushort) ADV_CHIP_ID_WORD); + asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) | + ADV_LIB_VERSION_MINOR; + asc_dvc->cfg->chip_version = + AdvGetChipVersion(iop_base, asc_dvc->bus_type); + + ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n", + (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1), + (ushort)ADV_CHIP_ID_BYTE); + + ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n", + (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0), + (ushort)ADV_CHIP_ID_WORD); + + /* + * Reset the chip to start and allow register writes. + */ + if (AdvFindSignature(iop_base) == 0) { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + return ADV_ERROR; + } else { + /* + * The caller must set 'chip_type' to a valid setting. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC3550 && + asc_dvc->chip_type != ADV_CHIP_ASC38C0800 && + asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { + asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - /* - * Reset the chip to start and allow register writes. - */ - if (AdvFindSignature(iop_base) == 0) - { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - return ADV_ERROR; - } - else { - /* - * The caller must set 'chip_type' to a valid setting. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC3550 && - asc_dvc->chip_type != ADV_CHIP_ASC38C0800 && - asc_dvc->chip_type != ADV_CHIP_ASC38C1600) - { - asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - /* - * Reset Chip. - */ - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, - ADV_CTRL_REG_CMD_RESET); - DvcSleepMilliSecond(100); - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, - ADV_CTRL_REG_CMD_WR_IO_REG); - - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - if ((status = AdvInitFrom38C1600EEP(asc_dvc)) == ADV_ERROR) - { - return ADV_ERROR; - } - } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) - { - if ((status = AdvInitFrom38C0800EEP(asc_dvc)) == ADV_ERROR) - { - return ADV_ERROR; - } - } else - { - if ((status = AdvInitFrom3550EEP(asc_dvc)) == ADV_ERROR) - { - return ADV_ERROR; - } - } - warn_code |= status; - } + /* + * Reset Chip. + */ + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, + ADV_CTRL_REG_CMD_RESET); + DvcSleepMilliSecond(100); + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, + ADV_CTRL_REG_CMD_WR_IO_REG); + + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + if ((status = + AdvInitFrom38C1600EEP(asc_dvc)) == ADV_ERROR) { + return ADV_ERROR; + } + } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + if ((status = + AdvInitFrom38C0800EEP(asc_dvc)) == ADV_ERROR) { + return ADV_ERROR; + } + } else { + if ((status = AdvInitFrom3550EEP(asc_dvc)) == ADV_ERROR) { + return ADV_ERROR; + } + } + warn_code |= status; + } - return warn_code; + return warn_code; } /* @@ -14535,574 +14325,563 @@ AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) * * Needed after initialization for error recovery. */ -STATIC int -AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) +static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADV_DCNT sum; - int begin_addr; - int end_addr; - ushort code_sum; - int word; - int j; - int adv_asc3550_expanded_size; - ADV_CARR_T *carrp; - ADV_DCNT contig_len; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; - int i; - ushort scsi_cfg1; - uchar tid; - ushort bios_mem[ASC_MC_BIOSLEN/2]; /* BIOS RISC Memory 0x40-0x8F. */ - ushort wdtr_able = 0, sdtr_able, tagqng_able; - uchar max_cmd[ADV_MAX_TID + 1]; - - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) - { - return ADV_ERROR; - } - - /* - * The caller must set 'chip_type' to ADV_CHIP_ASC3550. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC3550) - { - asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - warn_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * Save the RISC memory BIOS region before writing the microcode. - * The BIOS may already be loaded and using its RISC LRAM region - * so its region must be saved and restored. - * - * Note: This code makes the assumption, which is currently true, - * that a chip reset does not clear RISC LRAM. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Save current per TID negotiated values. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA) - { - ushort bios_version, major, minor; - - bios_version = bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM)/2]; - major = (bios_version >> 12) & 0xF; - minor = (bios_version >> 8) & 0xF; - if (major < 3 || (major == 3 && minor == 1)) - { - /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */ - AdvReadWordLram(iop_base, 0x120, wdtr_able); - } else - { - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - } - } - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - */ - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - /* Assume the following compressed format of the microcode buffer: - * - * 254 word (508 byte) table indexed by byte code followed - * by the following byte codes: - * - * 1-Byte Code: - * 00: Emit word 0 in table. - * 01: Emit word 1 in table. - * . - * FD: Emit word 253 in table. - * - * Multi-Byte Code: - * FE WW WW: (3 byte code) Word to emit is the next word WW WW. - * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. - */ - word = 0; - for (i = 253 * 2; i < _adv_asc3550_size; i++) - { - if (_adv_asc3550_buf[i] == 0xff) - { - for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc3550_buf[i + 3] << 8) | - _adv_asc3550_buf[i + 2])); - word++; - } - i += 3; - } else if (_adv_asc3550_buf[i] == 0xfe) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc3550_buf[i + 2] << 8) | - _adv_asc3550_buf[i + 1])); - i += 2; - word++; - } else - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | - _adv_asc3550_buf[_adv_asc3550_buf[i] * 2])); - word++; - } - } - - /* - * Set 'word' for later use to clear the rest of memory and save - * the expanded mcode size. - */ - word *= 2; - adv_asc3550_expanded_size = word; - - /* - * Clear the rest of ASC-3550 Internal RAM (8KB). - */ - for (; word < ADV_3550_MEMSIZE; word += 2) - { - AdvWriteWordAutoIncLram(iop_base, 0); - } - - /* - * Verify the microcode checksum. - */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - for (word = 0; word < adv_asc3550_expanded_size; word += 2) - { - sum += AdvReadWordAutoIncLram(iop_base); - } - - if (sum != _adv_asc3550_chksum) - { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return ADV_ERROR; - } - - /* - * Restore the RISC memory BIOS region. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Calculate and write the microcode code checksum to the microcode - * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). - */ - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); - AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); - code_sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); - for (word = begin_addr; word < end_addr; word += 2) - { - code_sum += AdvReadWordAutoIncLram(iop_base); - } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - - /* - * Read and save microcode version and date. - */ - AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date); - AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version); - - /* - * Set the chip type to indicate the ASC3550. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550); - - /* - * If the PCI Configuration Command Register "Parity Error Response - * Control" Bit was clear (0), then set the microcode variable - * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode - * to ignore DMA parity errors. - */ - if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) - { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_IGNORE_PERR; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO - * threshold of 128 bytes. This register is only accessible to the host. - */ - AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, - START_CTL_EMFU | READ_CMD_MRM); - - /* - * Microcode operating variables for WDTR, SDTR, and command tag - * queuing will be set in AdvInquiryHandling() based on what a - * device reports it is capable of in Inquiry byte 7. - * - * If SCSI Bus Resets have been disabled, then directly set - * SDTR and WDTR from the EEPROM configuration. This will allow - * the BIOS and warm boot to work without a SCSI bus hang on - * the Inquiry caused by host and target mismatched DTR values. - * Without the SCSI Bus Reset, before an Inquiry a device can't - * be assumed to be in Asynchronous, Narrow mode. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) - { - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, asc_dvc->wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, asc_dvc->sdtr_able); - } - - /* - * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID - * bitmask. These values determine the maximum SDTR speed negotiated - * with a device. - * - * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them - * without determining here whether the device supports SDTR. - * - * 4-bit speed SDTR speed name - * =========== =============== - * 0000b (0x0) SDTR disabled - * 0001b (0x1) 5 Mhz - * 0010b (0x2) 10 Mhz - * 0011b (0x3) 20 Mhz (Ultra) - * 0100b (0x4) 40 Mhz (LVD/Ultra2) - * 0101b (0x5) 80 Mhz (LVD2/Ultra3) - * 0110b (0x6) Undefined - * . - * 1111b (0xF) Undefined - */ - word = 0; - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) - { - /* Set Ultra speed for TID 'tid'. */ - word |= (0x3 << (4 * (tid % 4))); - } else - { - /* Set Fast speed for TID 'tid'. */ - word |= (0x2 << (4 * (tid % 4))); - } - if (tid == 3) /* Check if done with sdtr_speed1. */ - { - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word); - word = 0; - } else if (tid == 7) /* Check if done with sdtr_speed2. */ - { - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word); - word = 0; - } else if (tid == 11) /* Check if done with sdtr_speed3. */ - { - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word); - word = 0; - } else if (tid == 15) /* Check if done with sdtr_speed4. */ - { - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word); - /* End of loop. */ - } - } - - /* - * Set microcode operating variable for the disconnect per TID bitmask. - */ - AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable); + AdvPortAddr iop_base; + ushort warn_code; + ADV_DCNT sum; + int begin_addr; + int end_addr; + ushort code_sum; + int word; + int j; + int adv_asc3550_expanded_size; + ADV_CARR_T *carrp; + ADV_DCNT contig_len; + ADV_SDCNT buf_size; + ADV_PADDR carr_paddr; + int i; + ushort scsi_cfg1; + uchar tid; + ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ + ushort wdtr_able = 0, sdtr_able, tagqng_able; + uchar max_cmd[ADV_MAX_TID + 1]; + + /* If there is already an error, don't continue. */ + if (asc_dvc->err_code != 0) { + return ADV_ERROR; + } - /* - * Set SCSI_CFG0 Microcode Default Value. - * - * The microcode will set the SCSI_CFG0 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, - PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | - asc_dvc->chip_scsi_id); + /* + * The caller must set 'chip_type' to ADV_CHIP_ASC3550. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC3550) { + asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - /* - * Determine SCSI_CFG1 Microcode Default Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ + warn_code = 0; + iop_base = asc_dvc->iop_base; + + /* + * Save the RISC memory BIOS region before writing the microcode. + * The BIOS may already be loaded and using its RISC LRAM region + * so its region must be saved and restored. + * + * Note: This code makes the assumption, which is currently true, + * that a chip reset does not clear RISC LRAM. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* Read current SCSI_CFG1 Register value. */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + /* + * Save current per TID negotiated values. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) { + ushort bios_version, major, minor; + + bios_version = + bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2]; + major = (bios_version >> 12) & 0xF; + minor = (bios_version >> 8) & 0xF; + if (major < 3 || (major == 3 && minor == 1)) { + /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */ + AdvReadWordLram(iop_base, 0x120, wdtr_able); + } else { + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + } + } + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - /* - * If all three connectors are in use, return an error. - */ - if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 || - (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) - { - asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION; - return ADV_ERROR; - } + /* + * Load the Microcode + * + * Write the microcode image to RISC memory starting at address 0. + */ + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + /* Assume the following compressed format of the microcode buffer: + * + * 254 word (508 byte) table indexed by byte code followed + * by the following byte codes: + * + * 1-Byte Code: + * 00: Emit word 0 in table. + * 01: Emit word 1 in table. + * . + * FD: Emit word 253 in table. + * + * Multi-Byte Code: + * FE WW WW: (3 byte code) Word to emit is the next word WW WW. + * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. + */ + word = 0; + for (i = 253 * 2; i < _adv_asc3550_size; i++) { + if (_adv_asc3550_buf[i] == 0xff) { + for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc3550_buf + [i + + 3] << 8) | + _adv_asc3550_buf + [i + 2])); + word++; + } + i += 3; + } else if (_adv_asc3550_buf[i] == 0xfe) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc3550_buf[i + + 2] + << 8) | + _adv_asc3550_buf[i + + 1])); + i += 2; + word++; + } else { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2])); + word++; + } + } - /* - * If the internal narrow cable is reversed all of the SCSI_CTRL - * register signals will be set. Check for and return an error if - * this condition is found. - */ - if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) - { - asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; - return ADV_ERROR; - } + /* + * Set 'word' for later use to clear the rest of memory and save + * the expanded mcode size. + */ + word *= 2; + adv_asc3550_expanded_size = word; + + /* + * Clear the rest of ASC-3550 Internal RAM (8KB). + */ + for (; word < ADV_3550_MEMSIZE; word += 2) { + AdvWriteWordAutoIncLram(iop_base, 0); + } - /* - * If this is a differential board and a single-ended device - * is attached to one of the connectors, return an error. - */ - if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) - { - asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE; - return ADV_ERROR; - } + /* + * Verify the microcode checksum. + */ + sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - /* - * If automatic termination control is enabled, then set the - * termination value based on a table listed in a_condor.h. - * - * If manual termination was specified with an EEPROM setting - * then 'termination' was set-up in AdvInitFrom3550EEPROM() and - * is ready to be 'ored' into SCSI_CFG1. - */ - if (asc_dvc->cfg->termination == 0) - { - /* - * The software always controls termination by setting TERM_CTL_SEL. - * If TERM_CTL_SEL were set to 0, the hardware would set termination. - */ - asc_dvc->cfg->termination |= TERM_CTL_SEL; - - switch(scsi_cfg1 & CABLE_DETECT) - { - /* TERM_CTL_H: on, TERM_CTL_L: on */ - case 0x3: case 0x7: case 0xB: case 0xD: case 0xE: case 0xF: - asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L); - break; - - /* TERM_CTL_H: on, TERM_CTL_L: off */ - case 0x1: case 0x5: case 0x9: case 0xA: case 0xC: - asc_dvc->cfg->termination |= TERM_CTL_H; - break; - - /* TERM_CTL_H: off, TERM_CTL_L: off */ - case 0x2: case 0x6: - break; - } - } + for (word = 0; word < adv_asc3550_expanded_size; word += 2) { + sum += AdvReadWordAutoIncLram(iop_base); + } - /* - * Clear any set TERM_CTL_H and TERM_CTL_L bits. - */ - scsi_cfg1 &= ~TERM_CTL; + if (sum != _adv_asc3550_chksum) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return ADV_ERROR; + } - /* - * Invert the TERM_CTL_H and TERM_CTL_L bits and then - * set 'scsi_cfg1'. The TERM_POL bit does not need to be - * referenced, because the hardware internally inverts - * the Termination High and Low bits if TERM_POL is set. - */ - scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL)); + /* + * Restore the RISC memory BIOS region. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* - * Set SCSI_CFG1 Microcode Default Value - * - * Set filter value and possibly modified termination control - * bits in the Microcode SCSI_CFG1 Register Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, - FLTR_DISABLE | scsi_cfg1); + /* + * Calculate and write the microcode code checksum to the microcode + * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). + */ + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); + AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); + code_sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); + for (word = begin_addr; word < end_addr; word += 2) { + code_sum += AdvReadWordAutoIncLram(iop_base); + } + AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); + + /* + * Read and save microcode version and date. + */ + AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, + asc_dvc->cfg->mcode_date); + AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, + asc_dvc->cfg->mcode_version); + + /* + * Set the chip type to indicate the ASC3550. + */ + AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550); + + /* + * If the PCI Configuration Command Register "Parity Error Response + * Control" Bit was clear (0), then set the microcode variable + * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode + * to ignore DMA parity errors. + */ + if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_IGNORE_PERR; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - /* - * Set MEM_CFG Microcode Default Value - * - * The microcode will set the MEM_CFG register using this value - * after it is started below. - * - * MEM_CFG may be accessed as a word or byte, but only bits 0-7 - * are defined. - * - * ASC-3550 has 8KB internal memory. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - BIOS_EN | RAM_SZ_8KB); + /* + * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO + * threshold of 128 bytes. This register is only accessible to the host. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + START_CTL_EMFU | READ_CMD_MRM); + + /* + * Microcode operating variables for WDTR, SDTR, and command tag + * queuing will be set in AdvInquiryHandling() based on what a + * device reports it is capable of in Inquiry byte 7. + * + * If SCSI Bus Resets have been disabled, then directly set + * SDTR and WDTR from the EEPROM configuration. This will allow + * the BIOS and warm boot to work without a SCSI bus hang on + * the Inquiry caused by host and target mismatched DTR values. + * Without the SCSI Bus Reset, before an Inquiry a device can't + * be assumed to be in Asynchronous, Narrow mode. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + asc_dvc->wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + asc_dvc->sdtr_able); + } - /* - * Set SEL_MASK Microcode Default Value - * - * The microcode will set the SEL_MASK register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, - ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + /* + * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID + * bitmask. These values determine the maximum SDTR speed negotiated + * with a device. + * + * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them + * without determining here whether the device supports SDTR. + * + * 4-bit speed SDTR speed name + * =========== =============== + * 0000b (0x0) SDTR disabled + * 0001b (0x1) 5 Mhz + * 0010b (0x2) 10 Mhz + * 0011b (0x3) 20 Mhz (Ultra) + * 0100b (0x4) 40 Mhz (LVD/Ultra2) + * 0101b (0x5) 80 Mhz (LVD2/Ultra3) + * 0110b (0x6) Undefined + * . + * 1111b (0xF) Undefined + */ + word = 0; + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) { + /* Set Ultra speed for TID 'tid'. */ + word |= (0x3 << (4 * (tid % 4))); + } else { + /* Set Fast speed for TID 'tid'. */ + word |= (0x2 << (4 * (tid % 4))); + } + if (tid == 3) { /* Check if done with sdtr_speed1. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word); + word = 0; + } else if (tid == 7) { /* Check if done with sdtr_speed2. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word); + word = 0; + } else if (tid == 11) { /* Check if done with sdtr_speed3. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word); + word = 0; + } else if (tid == 15) { /* Check if done with sdtr_speed4. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word); + /* End of loop. */ + } + } - /* - * Build carrier freelist. - * - * Driver must have already allocated memory and set 'carrier_buf'. - */ - ASC_ASSERT(asc_dvc->carrier_buf != NULL); - - carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); - asc_dvc->carr_freelist = NULL; - if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) - { - buf_size = ADV_CARRIER_BUFSIZE; - } else - { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); - } + /* + * Set microcode operating variable for the disconnect per TID bitmask. + */ + AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, + asc_dvc->cfg->disc_enable); + + /* + * Set SCSI_CFG0 Microcode Default Value. + * + * The microcode will set the SCSI_CFG0 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, + PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | + asc_dvc->chip_scsi_id); + + /* + * Determine SCSI_CFG1 Microcode Default Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + + /* Read current SCSI_CFG1 Register value. */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + + /* + * If all three connectors are in use, return an error. + */ + if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 || + (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) { + asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION; + return ADV_ERROR; + } - do { - /* - * Get physical address of the carrier 'carrp'. - */ - contig_len = sizeof(ADV_CARR_T); - carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL, (uchar *) carrp, - (ADV_SDCNT *) &contig_len, ADV_IS_CARRIER_FLAG)); - - buf_size -= sizeof(ADV_CARR_T); - - /* - * If the current carrier is not physically contiguous, then - * maybe there was a page crossing. Try the next carrier aligned - * start address. - */ - if (contig_len < sizeof(ADV_CARR_T)) - { - carrp++; - continue; - } - - carrp->carr_pa = carr_paddr; - carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - - /* - * Insert the carrier at the beginning of the freelist. - */ - carrp->next_vpa = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = carrp; - - carrp++; - } - while (buf_size > 0); + /* + * If the internal narrow cable is reversed all of the SCSI_CTRL + * register signals will be set. Check for and return an error if + * this condition is found. + */ + if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { + asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; + return ADV_ERROR; + } - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ + /* + * If this is a differential board and a single-ended device + * is attached to one of the connectors, return an error. + */ + if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) { + asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE; + return ADV_ERROR; + } - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + /* + * If automatic termination control is enabled, then set the + * termination value based on a table listed in a_condor.h. + * + * If manual termination was specified with an EEPROM setting + * then 'termination' was set-up in AdvInitFrom3550EEPROM() and + * is ready to be 'ored' into SCSI_CFG1. + */ + if (asc_dvc->cfg->termination == 0) { + /* + * The software always controls termination by setting TERM_CTL_SEL. + * If TERM_CTL_SEL were set to 0, the hardware would set termination. + */ + asc_dvc->cfg->termination |= TERM_CTL_SEL; + + switch (scsi_cfg1 & CABLE_DETECT) { + /* TERM_CTL_H: on, TERM_CTL_L: on */ + case 0x3: + case 0x7: + case 0xB: + case 0xD: + case 0xE: + case 0xF: + asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L); + break; + + /* TERM_CTL_H: on, TERM_CTL_L: off */ + case 0x1: + case 0x5: + case 0x9: + case 0xA: + case 0xC: + asc_dvc->cfg->termination |= TERM_CTL_H; + break; + + /* TERM_CTL_H: off, TERM_CTL_L: off */ + case 0x2: + case 0x6: + break; + } + } - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + /* + * Clear any set TERM_CTL_H and TERM_CTL_L bits. + */ + scsi_cfg1 &= ~TERM_CTL; + + /* + * Invert the TERM_CTL_H and TERM_CTL_L bits and then + * set 'scsi_cfg1'. The TERM_POL bit does not need to be + * referenced, because the hardware internally inverts + * the Termination High and Low bits if TERM_POL is set. + */ + scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL)); + + /* + * Set SCSI_CFG1 Microcode Default Value + * + * Set filter value and possibly modified termination control + * bits in the Microcode SCSI_CFG1 Register Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, + FLTR_DISABLE | scsi_cfg1); + + /* + * Set MEM_CFG Microcode Default Value + * + * The microcode will set the MEM_CFG register using this value + * after it is started below. + * + * MEM_CFG may be accessed as a word or byte, but only bits 0-7 + * are defined. + * + * ASC-3550 has 8KB internal memory. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + BIOS_EN | RAM_SZ_8KB); + + /* + * Set SEL_MASK Microcode Default Value + * + * The microcode will set the SEL_MASK register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, + ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + + /* + * Build carrier freelist. + * + * Driver must have already allocated memory and set 'carrier_buf'. + */ + ASC_ASSERT(asc_dvc->carrier_buf != NULL); + + carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); + asc_dvc->carr_freelist = NULL; + if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) { + buf_size = ADV_CARRIER_BUFSIZE; + } else { + buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); + } - /* - * Set RISC ICQ physical address start value. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + do { + /* + * Get physical address of the carrier 'carrp'. + */ + contig_len = sizeof(ADV_CARR_T); + carr_paddr = + cpu_to_le32(DvcGetPhyAddr + (asc_dvc, NULL, (uchar *)carrp, + (ADV_SDCNT *)&contig_len, + ADV_IS_CARRIER_FLAG)); - /* - * Set-up the RISC->Host Initiator Response Queue (IRQ). - */ - if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + buf_size -= sizeof(ADV_CARR_T); - /* - * The first command completed by the RISC will be placed in - * the stopper. - * - * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is - * completed the RISC will set the ASC_RQ_STOPPER bit. - */ - asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - - /* - * Set RISC IRQ physical address start value. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); - asc_dvc->carr_pending_cnt = 0; + /* + * If the current carrier is not physically contiguous, then + * maybe there was a page crossing. Try the next carrier aligned + * start address. + */ + if (contig_len < sizeof(ADV_CARR_T)) { + carrp++; + continue; + } + + carrp->carr_pa = carr_paddr; + carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR)); + /* + * Insert the carrier at the beginning of the freelist. + */ + carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = carrp; - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); + carrp++; + } + while (buf_size > 0); - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + /* + * Set-up the Host->RISC Initiator Command Queue (ICQ). + */ - /* - * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus - * Resets should be performed. The RISC has to be running - * to issue a SCSI Bus Reset. - */ - if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) - { - /* - * If the BIOS Signature is present in memory, restore the - * BIOS Handshake Configuration Table and do not perform - * a SCSI Bus Reset. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA) - { - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - } else - { - if (AdvResetSB(asc_dvc) != ADV_TRUE) - { - warn_code = ASC_WARN_BUSRESET_ERROR; - } - } - } + if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + + /* + * The first command issued will be placed in the stopper carrier. + */ + asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC ICQ physical address start value. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + + /* + * Set-up the RISC->Host Initiator Response Queue (IRQ). + */ + if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + + /* + * The first command completed by the RISC will be placed in + * the stopper. + * + * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is + * completed the RISC will set the ASC_RQ_STOPPER bit. + */ + asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC IRQ physical address start value. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); + asc_dvc->carr_pending_cnt = 0; + + AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, + (ADV_INTR_ENABLE_HOST_INTR | + ADV_INTR_ENABLE_GLOBAL_INTR)); + + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); + AdvWriteWordRegister(iop_base, IOPW_PC, word); + + /* finally, finally, gentlemen, start your engine */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + + /* + * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus + * Resets should be performed. The RISC has to be running + * to issue a SCSI Bus Reset. + */ + if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { + /* + * If the BIOS Signature is present in memory, restore the + * BIOS Handshake Configuration Table and do not perform + * a SCSI Bus Reset. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == + 0x55AA) { + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + } else { + if (AdvResetSB(asc_dvc) != ADV_TRUE) { + warn_code = ASC_WARN_BUSRESET_ERROR; + } + } + } - return warn_code; + return warn_code; } /* @@ -15115,619 +14894,610 @@ AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) * * Needed after initialization for error recovery. */ -STATIC int -AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) +static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADV_DCNT sum; - int begin_addr; - int end_addr; - ushort code_sum; - int word; - int j; - int adv_asc38C0800_expanded_size; - ADV_CARR_T *carrp; - ADV_DCNT contig_len; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; - int i; - ushort scsi_cfg1; - uchar byte; - uchar tid; - ushort bios_mem[ASC_MC_BIOSLEN/2]; /* BIOS RISC Memory 0x40-0x8F. */ - ushort wdtr_able, sdtr_able, tagqng_able; - uchar max_cmd[ADV_MAX_TID + 1]; - - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) - { - return ADV_ERROR; - } - - /* - * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) - { - asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - warn_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * Save the RISC memory BIOS region before writing the microcode. - * The BIOS may already be loaded and using its RISC LRAM region - * so its region must be saved and restored. - * - * Note: This code makes the assumption, which is currently true, - * that a chip reset does not clear RISC LRAM. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Save current per TID negotiated values. - */ - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * RAM BIST (RAM Built-In Self Test) - * - * Address : I/O base + offset 0x38h register (byte). - * Function: Bit 7-6(RW) : RAM mode - * Normal Mode : 0x00 - * Pre-test Mode : 0x40 - * RAM Test Mode : 0x80 - * Bit 5 : unused - * Bit 4(RO) : Done bit - * Bit 3-0(RO) : Status - * Host Error : 0x08 - * Int_RAM Error : 0x04 - * RISC Error : 0x02 - * SCSI Error : 0x01 - * No Error : 0x00 - * - * Note: RAM BIST code should be put right here, before loading the - * microcode and after saving the RISC memory BIOS region. - */ - - /* - * LRAM Pre-test - * - * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. - * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return - * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset - * to NORMAL_MODE, return an error too. - */ - for (i = 0; i < 2; i++) - { - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & 0x0F) != PRE_TEST_VALUE) - { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) - != NORMAL_VALUE) - { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - } - - /* - * LRAM Test - It takes about 1.5 ms to run through the test. - * - * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. - * If Done bit not set or Status not 0, save register byte, set the - * err_code, and return an error. - */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ - - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) - { - /* Get here if Done bit not set or Status not 0. */ - asc_dvc->bist_err_code = byte; /* for BIOS display message */ - asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; - return ADV_ERROR; - } - - /* We need to reset back to normal mode after LRAM test passes. */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - - /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - * - */ - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - /* Assume the following compressed format of the microcode buffer: - * - * 254 word (508 byte) table indexed by byte code followed - * by the following byte codes: - * - * 1-Byte Code: - * 00: Emit word 0 in table. - * 01: Emit word 1 in table. - * . - * FD: Emit word 253 in table. - * - * Multi-Byte Code: - * FE WW WW: (3 byte code) Word to emit is the next word WW WW. - * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. - */ - word = 0; - for (i = 253 * 2; i < _adv_asc38C0800_size; i++) - { - if (_adv_asc38C0800_buf[i] == 0xff) - { - for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C0800_buf[i + 3] << 8) | - _adv_asc38C0800_buf[i + 2])); - word++; - } - i += 3; - } else if (_adv_asc38C0800_buf[i] == 0xfe) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C0800_buf[i + 2] << 8) | - _adv_asc38C0800_buf[i + 1])); - i += 2; - word++; - } else - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | - _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2])); - word++; - } - } - - /* - * Set 'word' for later use to clear the rest of memory and save - * the expanded mcode size. - */ - word *= 2; - adv_asc38C0800_expanded_size = word; - - /* - * Clear the rest of ASC-38C0800 Internal RAM (16KB). - */ - for (; word < ADV_38C0800_MEMSIZE; word += 2) - { - AdvWriteWordAutoIncLram(iop_base, 0); - } - - /* - * Verify the microcode checksum. - */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) - { - sum += AdvReadWordAutoIncLram(iop_base); - } - ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i); - - ASC_DBG2(1, - "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n", - (ulong) sum, (ulong) _adv_asc38C0800_chksum); - - if (sum != _adv_asc38C0800_chksum) - { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return ADV_ERROR; - } - - /* - * Restore the RISC memory BIOS region. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Calculate and write the microcode code checksum to the microcode - * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). - */ - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); - AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); - code_sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); - for (word = begin_addr; word < end_addr; word += 2) - { - code_sum += AdvReadWordAutoIncLram(iop_base); - } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - - /* - * Read microcode version and date. - */ - AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date); - AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version); - - /* - * Set the chip type to indicate the ASC38C0800. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800); - - /* - * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. - * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current - * cable detection and then we are able to read C_DET[3:0]. - * - * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 - * Microcode Default Value' section below. - */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, scsi_cfg1 | DIS_TERM_DRV); - - /* - * If the PCI Configuration Command Register "Parity Error Response - * Control" Bit was clear (0), then set the microcode variable - * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode - * to ignore DMA parity errors. - */ - if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) - { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_IGNORE_PERR; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2] - * bits for the default FIFO threshold. - * - * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes. - * - * For DMA Errata #4 set the BC_THRESH_ENB bit. - */ - AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, - BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM); - - /* - * Microcode operating variables for WDTR, SDTR, and command tag - * queuing will be set in AdvInquiryHandling() based on what a - * device reports it is capable of in Inquiry byte 7. - * - * If SCSI Bus Resets have been disabled, then directly set - * SDTR and WDTR from the EEPROM configuration. This will allow - * the BIOS and warm boot to work without a SCSI bus hang on - * the Inquiry caused by host and target mismatched DTR values. - * Without the SCSI Bus Reset, before an Inquiry a device can't - * be assumed to be in Asynchronous, Narrow mode. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) - { - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, asc_dvc->wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, asc_dvc->sdtr_able); - } - - /* - * Set microcode operating variables for DISC and SDTR_SPEED1, - * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM - * configuration values. - * - * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them - * without determining here whether the device supports SDTR. - */ - AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); + AdvPortAddr iop_base; + ushort warn_code; + ADV_DCNT sum; + int begin_addr; + int end_addr; + ushort code_sum; + int word; + int j; + int adv_asc38C0800_expanded_size; + ADV_CARR_T *carrp; + ADV_DCNT contig_len; + ADV_SDCNT buf_size; + ADV_PADDR carr_paddr; + int i; + ushort scsi_cfg1; + uchar byte; + uchar tid; + ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ + ushort wdtr_able, sdtr_able, tagqng_able; + uchar max_cmd[ADV_MAX_TID + 1]; + + /* If there is already an error, don't continue. */ + if (asc_dvc->err_code != 0) { + return ADV_ERROR; + } - /* - * Set SCSI_CFG0 Microcode Default Value. - * - * The microcode will set the SCSI_CFG0 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, - PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | - asc_dvc->chip_scsi_id); + /* + * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) { + asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - /* - * Determine SCSI_CFG1 Microcode Default Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ + warn_code = 0; + iop_base = asc_dvc->iop_base; + + /* + * Save the RISC memory BIOS region before writing the microcode. + * The BIOS may already be loaded and using its RISC LRAM region + * so its region must be saved and restored. + * + * Note: This code makes the assumption, which is currently true, + * that a chip reset does not clear RISC LRAM. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* Read current SCSI_CFG1 Register value. */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + /* + * Save current per TID negotiated values. + */ + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - /* - * If the internal narrow cable is reversed all of the SCSI_CTRL - * register signals will be set. Check for and return an error if - * this condition is found. - */ - if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) - { - asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; - return ADV_ERROR; - } + /* + * RAM BIST (RAM Built-In Self Test) + * + * Address : I/O base + offset 0x38h register (byte). + * Function: Bit 7-6(RW) : RAM mode + * Normal Mode : 0x00 + * Pre-test Mode : 0x40 + * RAM Test Mode : 0x80 + * Bit 5 : unused + * Bit 4(RO) : Done bit + * Bit 3-0(RO) : Status + * Host Error : 0x08 + * Int_RAM Error : 0x04 + * RISC Error : 0x02 + * SCSI Error : 0x01 + * No Error : 0x00 + * + * Note: RAM BIST code should be put right here, before loading the + * microcode and after saving the RISC memory BIOS region. + */ + + /* + * LRAM Pre-test + * + * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. + * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return + * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset + * to NORMAL_MODE, return an error too. + */ + for (i = 0; i < 2; i++) { + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 + || (byte & 0x0F) != PRE_TEST_VALUE) { + asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } + + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ + if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) + != NORMAL_VALUE) { + asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } + } - /* - * All kind of combinations of devices attached to one of four connectors - * are acceptable except HVD device attached. For example, LVD device can - * be attached to SE connector while SE device attached to LVD connector. - * If LVD device attached to SE connector, it only runs up to Ultra speed. - * - * If an HVD device is attached to one of LVD connectors, return an error. - * However, there is no way to detect HVD device attached to SE connectors. - */ - if (scsi_cfg1 & HVD) - { - asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; - return ADV_ERROR; - } + /* + * LRAM Test - It takes about 1.5 ms to run through the test. + * + * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. + * If Done bit not set or Status not 0, save register byte, set the + * err_code, and return an error. + */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ + + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { + /* Get here if Done bit not set or Status not 0. */ + asc_dvc->bist_err_code = byte; /* for BIOS display message */ + asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; + return ADV_ERROR; + } - /* - * If either SE or LVD automatic termination control is enabled, then - * set the termination value based on a table listed in a_condor.h. - * - * If manual termination was specified with an EEPROM setting then - * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to - * be 'ored' into SCSI_CFG1. - */ - if ((asc_dvc->cfg->termination & TERM_SE) == 0) - { - /* SE automatic termination control is enabled. */ - switch(scsi_cfg1 & C_DET_SE) - { - /* TERM_SE_HI: on, TERM_SE_LO: on */ - case 0x1: case 0x2: case 0x3: - asc_dvc->cfg->termination |= TERM_SE; - break; - - /* TERM_SE_HI: on, TERM_SE_LO: off */ - case 0x0: - asc_dvc->cfg->termination |= TERM_SE_HI; - break; - } - } + /* We need to reset back to normal mode after LRAM test passes. */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + + /* + * Load the Microcode + * + * Write the microcode image to RISC memory starting at address 0. + * + */ + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + + /* Assume the following compressed format of the microcode buffer: + * + * 254 word (508 byte) table indexed by byte code followed + * by the following byte codes: + * + * 1-Byte Code: + * 00: Emit word 0 in table. + * 01: Emit word 1 in table. + * . + * FD: Emit word 253 in table. + * + * Multi-Byte Code: + * FE WW WW: (3 byte code) Word to emit is the next word WW WW. + * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. + */ + word = 0; + for (i = 253 * 2; i < _adv_asc38C0800_size; i++) { + if (_adv_asc38C0800_buf[i] == 0xff) { + for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C0800_buf + [i + + 3] << 8) | + _adv_asc38C0800_buf + [i + 2])); + word++; + } + i += 3; + } else if (_adv_asc38C0800_buf[i] == 0xfe) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C0800_buf + [i + + 2] << 8) | + _adv_asc38C0800_buf[i + + + 1])); + i += 2; + word++; + } else { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2])); + word++; + } + } - if ((asc_dvc->cfg->termination & TERM_LVD) == 0) - { - /* LVD automatic termination control is enabled. */ - switch(scsi_cfg1 & C_DET_LVD) - { - /* TERM_LVD_HI: on, TERM_LVD_LO: on */ - case 0x4: case 0x8: case 0xC: - asc_dvc->cfg->termination |= TERM_LVD; - break; - - /* TERM_LVD_HI: off, TERM_LVD_LO: off */ - case 0x0: - break; - } - } + /* + * Set 'word' for later use to clear the rest of memory and save + * the expanded mcode size. + */ + word *= 2; + adv_asc38C0800_expanded_size = word; + + /* + * Clear the rest of ASC-38C0800 Internal RAM (16KB). + */ + for (; word < ADV_38C0800_MEMSIZE; word += 2) { + AdvWriteWordAutoIncLram(iop_base, 0); + } - /* - * Clear any set TERM_SE and TERM_LVD bits. - */ - scsi_cfg1 &= (~TERM_SE & ~TERM_LVD); + /* + * Verify the microcode checksum. + */ + sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - /* - * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'. - */ - scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0); + for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) { + sum += AdvReadWordAutoIncLram(iop_base); + } + ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i); - /* - * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits - * and set possibly modified termination control bits in the Microcode - * SCSI_CFG1 Register Value. - */ - scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE); + ASC_DBG2(1, + "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n", + (ulong)sum, (ulong)_adv_asc38C0800_chksum); - /* - * Set SCSI_CFG1 Microcode Default Value - * - * Set possibly modified termination control and reset DIS_TERM_DRV - * bits in the Microcode SCSI_CFG1 Register Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); + if (sum != _adv_asc38C0800_chksum) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return ADV_ERROR; + } - /* - * Set MEM_CFG Microcode Default Value - * - * The microcode will set the MEM_CFG register using this value - * after it is started below. - * - * MEM_CFG may be accessed as a word or byte, but only bits 0-7 - * are defined. - * - * ASC-38C0800 has 16KB internal memory. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - BIOS_EN | RAM_SZ_16KB); + /* + * Restore the RISC memory BIOS region. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* - * Set SEL_MASK Microcode Default Value - * - * The microcode will set the SEL_MASK register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, - ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + /* + * Calculate and write the microcode code checksum to the microcode + * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). + */ + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); + AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); + code_sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); + for (word = begin_addr; word < end_addr; word += 2) { + code_sum += AdvReadWordAutoIncLram(iop_base); + } + AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); + + /* + * Read microcode version and date. + */ + AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, + asc_dvc->cfg->mcode_date); + AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, + asc_dvc->cfg->mcode_version); + + /* + * Set the chip type to indicate the ASC38C0800. + */ + AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800); + + /* + * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. + * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current + * cable detection and then we are able to read C_DET[3:0]. + * + * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 + * Microcode Default Value' section below. + */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, + scsi_cfg1 | DIS_TERM_DRV); + + /* + * If the PCI Configuration Command Register "Parity Error Response + * Control" Bit was clear (0), then set the microcode variable + * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode + * to ignore DMA parity errors. + */ + if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_IGNORE_PERR; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - /* - * Build the carrier freelist. - * - * Driver must have already allocated memory and set 'carrier_buf'. - */ - ASC_ASSERT(asc_dvc->carrier_buf != NULL); - - carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); - asc_dvc->carr_freelist = NULL; - if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) - { - buf_size = ADV_CARRIER_BUFSIZE; - } else - { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); - } + /* + * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2] + * bits for the default FIFO threshold. + * + * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes. + * + * For DMA Errata #4 set the BC_THRESH_ENB bit. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH | + READ_CMD_MRM); + + /* + * Microcode operating variables for WDTR, SDTR, and command tag + * queuing will be set in AdvInquiryHandling() based on what a + * device reports it is capable of in Inquiry byte 7. + * + * If SCSI Bus Resets have been disabled, then directly set + * SDTR and WDTR from the EEPROM configuration. This will allow + * the BIOS and warm boot to work without a SCSI bus hang on + * the Inquiry caused by host and target mismatched DTR values. + * Without the SCSI Bus Reset, before an Inquiry a device can't + * be assumed to be in Asynchronous, Narrow mode. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + asc_dvc->wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + asc_dvc->sdtr_able); + } - do { - /* - * Get physical address for the carrier 'carrp'. - */ - contig_len = sizeof(ADV_CARR_T); - carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL, (uchar *) carrp, - (ADV_SDCNT *) &contig_len, ADV_IS_CARRIER_FLAG)); - - buf_size -= sizeof(ADV_CARR_T); - - /* - * If the current carrier is not physically contiguous, then - * maybe there was a page crossing. Try the next carrier aligned - * start address. - */ - if (contig_len < sizeof(ADV_CARR_T)) - { - carrp++; - continue; - } - - carrp->carr_pa = carr_paddr; - carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - - /* - * Insert the carrier at the beginning of the freelist. - */ - carrp->next_vpa = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = carrp; - - carrp++; - } - while (buf_size > 0); + /* + * Set microcode operating variables for DISC and SDTR_SPEED1, + * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM + * configuration values. + * + * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them + * without determining here whether the device supports SDTR. + */ + AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, + asc_dvc->cfg->disc_enable); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); + + /* + * Set SCSI_CFG0 Microcode Default Value. + * + * The microcode will set the SCSI_CFG0 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, + PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | + asc_dvc->chip_scsi_id); + + /* + * Determine SCSI_CFG1 Microcode Default Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + + /* Read current SCSI_CFG1 Register value. */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + + /* + * If the internal narrow cable is reversed all of the SCSI_CTRL + * register signals will be set. Check for and return an error if + * this condition is found. + */ + if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { + asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; + return ADV_ERROR; + } - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ + /* + * All kind of combinations of devices attached to one of four connectors + * are acceptable except HVD device attached. For example, LVD device can + * be attached to SE connector while SE device attached to LVD connector. + * If LVD device attached to SE connector, it only runs up to Ultra speed. + * + * If an HVD device is attached to one of LVD connectors, return an error. + * However, there is no way to detect HVD device attached to SE connectors. + */ + if (scsi_cfg1 & HVD) { + asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; + return ADV_ERROR; + } - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + /* + * If either SE or LVD automatic termination control is enabled, then + * set the termination value based on a table listed in a_condor.h. + * + * If manual termination was specified with an EEPROM setting then + * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to + * be 'ored' into SCSI_CFG1. + */ + if ((asc_dvc->cfg->termination & TERM_SE) == 0) { + /* SE automatic termination control is enabled. */ + switch (scsi_cfg1 & C_DET_SE) { + /* TERM_SE_HI: on, TERM_SE_LO: on */ + case 0x1: + case 0x2: + case 0x3: + asc_dvc->cfg->termination |= TERM_SE; + break; + + /* TERM_SE_HI: on, TERM_SE_LO: off */ + case 0x0: + asc_dvc->cfg->termination |= TERM_SE_HI; + break; + } + } - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + if ((asc_dvc->cfg->termination & TERM_LVD) == 0) { + /* LVD automatic termination control is enabled. */ + switch (scsi_cfg1 & C_DET_LVD) { + /* TERM_LVD_HI: on, TERM_LVD_LO: on */ + case 0x4: + case 0x8: + case 0xC: + asc_dvc->cfg->termination |= TERM_LVD; + break; + + /* TERM_LVD_HI: off, TERM_LVD_LO: off */ + case 0x0: + break; + } + } - /* - * Set RISC ICQ physical address start value. - * carr_pa is LE, must be native before write - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + /* + * Clear any set TERM_SE and TERM_LVD bits. + */ + scsi_cfg1 &= (~TERM_SE & ~TERM_LVD); + + /* + * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'. + */ + scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0); + + /* + * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits + * and set possibly modified termination control bits in the Microcode + * SCSI_CFG1 Register Value. + */ + scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE); + + /* + * Set SCSI_CFG1 Microcode Default Value + * + * Set possibly modified termination control and reset DIS_TERM_DRV + * bits in the Microcode SCSI_CFG1 Register Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); + + /* + * Set MEM_CFG Microcode Default Value + * + * The microcode will set the MEM_CFG register using this value + * after it is started below. + * + * MEM_CFG may be accessed as a word or byte, but only bits 0-7 + * are defined. + * + * ASC-38C0800 has 16KB internal memory. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + BIOS_EN | RAM_SZ_16KB); + + /* + * Set SEL_MASK Microcode Default Value + * + * The microcode will set the SEL_MASK register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, + ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + + /* + * Build the carrier freelist. + * + * Driver must have already allocated memory and set 'carrier_buf'. + */ + ASC_ASSERT(asc_dvc->carrier_buf != NULL); + + carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); + asc_dvc->carr_freelist = NULL; + if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) { + buf_size = ADV_CARRIER_BUFSIZE; + } else { + buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); + } - /* - * Set-up the RISC->Host Initiator Response Queue (IRQ). - */ - if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + do { + /* + * Get physical address for the carrier 'carrp'. + */ + contig_len = sizeof(ADV_CARR_T); + carr_paddr = + cpu_to_le32(DvcGetPhyAddr + (asc_dvc, NULL, (uchar *)carrp, + (ADV_SDCNT *)&contig_len, + ADV_IS_CARRIER_FLAG)); - /* - * The first command completed by the RISC will be placed in - * the stopper. - * - * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is - * completed the RISC will set the ASC_RQ_STOPPER bit. - */ - asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + buf_size -= sizeof(ADV_CARR_T); - /* - * Set RISC IRQ physical address start value. - * - * carr_pa is LE, must be native before write * - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); - asc_dvc->carr_pending_cnt = 0; + /* + * If the current carrier is not physically contiguous, then + * maybe there was a page crossing. Try the next carrier aligned + * start address. + */ + if (contig_len < sizeof(ADV_CARR_T)) { + carrp++; + continue; + } + + carrp->carr_pa = carr_paddr; + carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR)); + /* + * Insert the carrier at the beginning of the freelist. + */ + carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = carrp; - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); + carrp++; + } + while (buf_size > 0); - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + /* + * Set-up the Host->RISC Initiator Command Queue (ICQ). + */ - /* - * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus - * Resets should be performed. The RISC has to be running - * to issue a SCSI Bus Reset. - */ - if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) - { - /* - * If the BIOS Signature is present in memory, restore the - * BIOS Handshake Configuration Table and do not perform - * a SCSI Bus Reset. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA) - { - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - } else - { - if (AdvResetSB(asc_dvc) != ADV_TRUE) - { - warn_code = ASC_WARN_BUSRESET_ERROR; - } - } - } + if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + + /* + * The first command issued will be placed in the stopper carrier. + */ + asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC ICQ physical address start value. + * carr_pa is LE, must be native before write + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + + /* + * Set-up the RISC->Host Initiator Response Queue (IRQ). + */ + if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + + /* + * The first command completed by the RISC will be placed in + * the stopper. + * + * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is + * completed the RISC will set the ASC_RQ_STOPPER bit. + */ + asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC IRQ physical address start value. + * + * carr_pa is LE, must be native before write * + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); + asc_dvc->carr_pending_cnt = 0; + + AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, + (ADV_INTR_ENABLE_HOST_INTR | + ADV_INTR_ENABLE_GLOBAL_INTR)); + + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); + AdvWriteWordRegister(iop_base, IOPW_PC, word); + + /* finally, finally, gentlemen, start your engine */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + + /* + * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus + * Resets should be performed. The RISC has to be running + * to issue a SCSI Bus Reset. + */ + if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { + /* + * If the BIOS Signature is present in memory, restore the + * BIOS Handshake Configuration Table and do not perform + * a SCSI Bus Reset. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == + 0x55AA) { + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + } else { + if (AdvResetSB(asc_dvc) != ADV_TRUE) { + warn_code = ASC_WARN_BUSRESET_ERROR; + } + } + } - return warn_code; + return warn_code; } /* @@ -15740,630 +15510,617 @@ AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) * * Needed after initialization for error recovery. */ -STATIC int -AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) +static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADV_DCNT sum; - int begin_addr; - int end_addr; - ushort code_sum; - long word; - int j; - int adv_asc38C1600_expanded_size; - ADV_CARR_T *carrp; - ADV_DCNT contig_len; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; - int i; - ushort scsi_cfg1; - uchar byte; - uchar tid; - ushort bios_mem[ASC_MC_BIOSLEN/2]; /* BIOS RISC Memory 0x40-0x8F. */ - ushort wdtr_able, sdtr_able, ppr_able, tagqng_able; - uchar max_cmd[ASC_MAX_TID + 1]; - - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) - { - return ADV_ERROR; - } - - /* - * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) - { - asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - warn_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * Save the RISC memory BIOS region before writing the microcode. - * The BIOS may already be loaded and using its RISC LRAM region - * so its region must be saved and restored. - * - * Note: This code makes the assumption, which is currently true, - * that a chip reset does not clear RISC LRAM. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Save current per TID negotiated values. - */ - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ASC_MAX_TID; tid++) - { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * RAM BIST (Built-In Self Test) - * - * Address : I/O base + offset 0x38h register (byte). - * Function: Bit 7-6(RW) : RAM mode - * Normal Mode : 0x00 - * Pre-test Mode : 0x40 - * RAM Test Mode : 0x80 - * Bit 5 : unused - * Bit 4(RO) : Done bit - * Bit 3-0(RO) : Status - * Host Error : 0x08 - * Int_RAM Error : 0x04 - * RISC Error : 0x02 - * SCSI Error : 0x01 - * No Error : 0x00 - * - * Note: RAM BIST code should be put right here, before loading the - * microcode and after saving the RISC memory BIOS region. - */ - - /* - * LRAM Pre-test - * - * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. - * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return - * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset - * to NORMAL_MODE, return an error too. - */ - for (i = 0; i < 2; i++) - { - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & 0x0F) != PRE_TEST_VALUE) - { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) - != NORMAL_VALUE) - { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - } - - /* - * LRAM Test - It takes about 1.5 ms to run through the test. - * - * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. - * If Done bit not set or Status not 0, save register byte, set the - * err_code, and return an error. - */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ - - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) - { - /* Get here if Done bit not set or Status not 0. */ - asc_dvc->bist_err_code = byte; /* for BIOS display message */ - asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; - return ADV_ERROR; - } - - /* We need to reset back to normal mode after LRAM test passes. */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - - /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - * - */ - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - /* - * Assume the following compressed format of the microcode buffer: - * - * 254 word (508 byte) table indexed by byte code followed - * by the following byte codes: - * - * 1-Byte Code: - * 00: Emit word 0 in table. - * 01: Emit word 1 in table. - * . - * FD: Emit word 253 in table. - * - * Multi-Byte Code: - * FE WW WW: (3 byte code) Word to emit is the next word WW WW. - * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. - */ - word = 0; - for (i = 253 * 2; i < _adv_asc38C1600_size; i++) - { - if (_adv_asc38C1600_buf[i] == 0xff) - { - for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C1600_buf[i + 3] << 8) | - _adv_asc38C1600_buf[i + 2])); - word++; - } - i += 3; - } else if (_adv_asc38C1600_buf[i] == 0xfe) - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C1600_buf[i + 2] << 8) | - _adv_asc38C1600_buf[i + 1])); - i += 2; - word++; - } else - { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | - _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2])); - word++; - } - } - - /* - * Set 'word' for later use to clear the rest of memory and save - * the expanded mcode size. - */ - word *= 2; - adv_asc38C1600_expanded_size = word; - - /* - * Clear the rest of ASC-38C1600 Internal RAM (32KB). - */ - for (; word < ADV_38C1600_MEMSIZE; word += 2) - { - AdvWriteWordAutoIncLram(iop_base, 0); - } - - /* - * Verify the microcode checksum. - */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) - { - sum += AdvReadWordAutoIncLram(iop_base); - } - - if (sum != _adv_asc38C1600_chksum) - { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return ADV_ERROR; - } - - /* - * Restore the RISC memory BIOS region. - */ - for (i = 0; i < ASC_MC_BIOSLEN/2; i++) - { - AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), bios_mem[i]); - } - - /* - * Calculate and write the microcode code checksum to the microcode - * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). - */ - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); - AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); - code_sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); - for (word = begin_addr; word < end_addr; word += 2) - { - code_sum += AdvReadWordAutoIncLram(iop_base); - } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - - /* - * Read microcode version and date. - */ - AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date); - AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version); - - /* - * Set the chip type to indicate the ASC38C1600. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600); - - /* - * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. - * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current - * cable detection and then we are able to read C_DET[3:0]. - * - * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 - * Microcode Default Value' section below. - */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, scsi_cfg1 | DIS_TERM_DRV); - - /* - * If the PCI Configuration Command Register "Parity Error Response - * Control" Bit was clear (0), then set the microcode variable - * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode - * to ignore DMA parity errors. - */ - if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) - { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_IGNORE_PERR; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * If the BIOS control flag AIPP (Asynchronous Information - * Phase Protection) disable bit is not set, then set the firmware - * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable - * AIPP checking and encoding. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) - { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_ENABLE_AIPP; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4], - * and START_CTL_TH [3:2]. - */ - AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, - FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM); - - /* - * Microcode operating variables for WDTR, SDTR, and command tag - * queuing will be set in AdvInquiryHandling() based on what a - * device reports it is capable of in Inquiry byte 7. - * - * If SCSI Bus Resets have been disabled, then directly set - * SDTR and WDTR from the EEPROM configuration. This will allow - * the BIOS and warm boot to work without a SCSI bus hang on - * the Inquiry caused by host and target mismatched DTR values. - * Without the SCSI Bus Reset, before an Inquiry a device can't - * be assumed to be in Asynchronous, Narrow mode. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) - { - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, asc_dvc->wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, asc_dvc->sdtr_able); - } + AdvPortAddr iop_base; + ushort warn_code; + ADV_DCNT sum; + int begin_addr; + int end_addr; + ushort code_sum; + long word; + int j; + int adv_asc38C1600_expanded_size; + ADV_CARR_T *carrp; + ADV_DCNT contig_len; + ADV_SDCNT buf_size; + ADV_PADDR carr_paddr; + int i; + ushort scsi_cfg1; + uchar byte; + uchar tid; + ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ + ushort wdtr_able, sdtr_able, ppr_able, tagqng_able; + uchar max_cmd[ASC_MAX_TID + 1]; + + /* If there is already an error, don't continue. */ + if (asc_dvc->err_code != 0) { + return ADV_ERROR; + } - /* - * Set microcode operating variables for DISC and SDTR_SPEED1, - * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM - * configuration values. - * - * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them - * without determining here whether the device supports SDTR. - */ - AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); + /* + * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { + asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - /* - * Set SCSI_CFG0 Microcode Default Value. - * - * The microcode will set the SCSI_CFG0 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, - PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | - asc_dvc->chip_scsi_id); + warn_code = 0; + iop_base = asc_dvc->iop_base; + + /* + * Save the RISC memory BIOS region before writing the microcode. + * The BIOS may already be loaded and using its RISC LRAM region + * so its region must be saved and restored. + * + * Note: This code makes the assumption, which is currently true, + * that a chip reset does not clear RISC LRAM. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* - * Calculate SCSI_CFG1 Microcode Default Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - * - * Each ASC-38C1600 function has only two cable detect bits. - * The bus mode override bits are in IOPB_SOFT_OVER_WR. - */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + /* + * Save current per TID negotiated values. + */ + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - /* - * If the cable is reversed all of the SCSI_CTRL register signals - * will be set. Check for and return an error if this condition is - * found. - */ - if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) - { - asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; - return ADV_ERROR; - } + /* + * RAM BIST (Built-In Self Test) + * + * Address : I/O base + offset 0x38h register (byte). + * Function: Bit 7-6(RW) : RAM mode + * Normal Mode : 0x00 + * Pre-test Mode : 0x40 + * RAM Test Mode : 0x80 + * Bit 5 : unused + * Bit 4(RO) : Done bit + * Bit 3-0(RO) : Status + * Host Error : 0x08 + * Int_RAM Error : 0x04 + * RISC Error : 0x02 + * SCSI Error : 0x01 + * No Error : 0x00 + * + * Note: RAM BIST code should be put right here, before loading the + * microcode and after saving the RISC memory BIOS region. + */ + + /* + * LRAM Pre-test + * + * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. + * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return + * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset + * to NORMAL_MODE, return an error too. + */ + for (i = 0; i < 2; i++) { + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 + || (byte & 0x0F) != PRE_TEST_VALUE) { + asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } + + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ + if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) + != NORMAL_VALUE) { + asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } + } - /* - * Each ASC-38C1600 function has two connectors. Only an HVD device - * can not be connected to either connector. An LVD device or SE device - * may be connected to either connecor. If an SE device is connected, - * then at most Ultra speed (20 Mhz) can be used on both connectors. - * - * If an HVD device is attached, return an error. - */ - if (scsi_cfg1 & HVD) - { - asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; - return ADV_ERROR; - } + /* + * LRAM Test - It takes about 1.5 ms to run through the test. + * + * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. + * If Done bit not set or Status not 0, save register byte, set the + * err_code, and return an error. + */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); + DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ + + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { + /* Get here if Done bit not set or Status not 0. */ + asc_dvc->bist_err_code = byte; /* for BIOS display message */ + asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; + return ADV_ERROR; + } - /* - * Each function in the ASC-38C1600 uses only the SE cable detect and - * termination because there are two connectors for each function. Each - * function may use either LVD or SE mode. Corresponding the SE automatic - * termination control EEPROM bits are used for each function. Each - * function has its own EEPROM. If SE automatic control is enabled for - * the function, then set the termination value based on a table listed - * in a_condor.h. - * - * If manual termination is specified in the EEPROM for the function, - * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is - * ready to be 'ored' into SCSI_CFG1. - */ - if ((asc_dvc->cfg->termination & TERM_SE) == 0) - { - /* SE automatic termination control is enabled. */ - switch(scsi_cfg1 & C_DET_SE) - { - /* TERM_SE_HI: on, TERM_SE_LO: on */ - case 0x1: case 0x2: case 0x3: - asc_dvc->cfg->termination |= TERM_SE; - break; - - case 0x0: - if (ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) == 0) - { - /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */ - } - else - { - /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */ - asc_dvc->cfg->termination |= TERM_SE_HI; - } - break; - } - } + /* We need to reset back to normal mode after LRAM test passes. */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + + /* + * Load the Microcode + * + * Write the microcode image to RISC memory starting at address 0. + * + */ + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + + /* + * Assume the following compressed format of the microcode buffer: + * + * 254 word (508 byte) table indexed by byte code followed + * by the following byte codes: + * + * 1-Byte Code: + * 00: Emit word 0 in table. + * 01: Emit word 1 in table. + * . + * FD: Emit word 253 in table. + * + * Multi-Byte Code: + * FE WW WW: (3 byte code) Word to emit is the next word WW WW. + * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. + */ + word = 0; + for (i = 253 * 2; i < _adv_asc38C1600_size; i++) { + if (_adv_asc38C1600_buf[i] == 0xff) { + for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C1600_buf + [i + + 3] << 8) | + _adv_asc38C1600_buf + [i + 2])); + word++; + } + i += 3; + } else if (_adv_asc38C1600_buf[i] == 0xfe) { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C1600_buf + [i + + 2] << 8) | + _adv_asc38C1600_buf[i + + + 1])); + i += 2; + word++; + } else { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2])); + word++; + } + } - /* - * Clear any set TERM_SE bits. - */ - scsi_cfg1 &= ~TERM_SE; + /* + * Set 'word' for later use to clear the rest of memory and save + * the expanded mcode size. + */ + word *= 2; + adv_asc38C1600_expanded_size = word; + + /* + * Clear the rest of ASC-38C1600 Internal RAM (32KB). + */ + for (; word < ADV_38C1600_MEMSIZE; word += 2) { + AdvWriteWordAutoIncLram(iop_base, 0); + } - /* - * Invert the TERM_SE bits and then set 'scsi_cfg1'. - */ - scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE); + /* + * Verify the microcode checksum. + */ + sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - /* - * Clear Big Endian and Terminator Polarity bits and set possibly - * modified termination control bits in the Microcode SCSI_CFG1 - * Register Value. - * - * Big Endian bit is not used even on big endian machines. - */ - scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL); + for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) { + sum += AdvReadWordAutoIncLram(iop_base); + } - /* - * Set SCSI_CFG1 Microcode Default Value - * - * Set possibly modified termination control bits in the Microcode - * SCSI_CFG1 Register Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); + if (sum != _adv_asc38C1600_chksum) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return ADV_ERROR; + } - /* - * Set MEM_CFG Microcode Default Value - * - * The microcode will set the MEM_CFG register using this value - * after it is started below. - * - * MEM_CFG may be accessed as a word or byte, but only bits 0-7 - * are defined. - * - * ASC-38C1600 has 32KB internal memory. - * - * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come - * out a special 16K Adv Library and Microcode version. After the issue - * resolved, we should turn back to the 32K support. Both a_condor.h and - * mcode.sas files also need to be updated. - * - * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - * BIOS_EN | RAM_SZ_32KB); - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, BIOS_EN | RAM_SZ_16KB); + /* + * Restore the RISC memory BIOS region. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - /* - * Set SEL_MASK Microcode Default Value - * - * The microcode will set the SEL_MASK register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, - ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + /* + * Calculate and write the microcode code checksum to the microcode + * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). + */ + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); + AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); + code_sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); + for (word = begin_addr; word < end_addr; word += 2) { + code_sum += AdvReadWordAutoIncLram(iop_base); + } + AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); + + /* + * Read microcode version and date. + */ + AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, + asc_dvc->cfg->mcode_date); + AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, + asc_dvc->cfg->mcode_version); + + /* + * Set the chip type to indicate the ASC38C1600. + */ + AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600); + + /* + * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. + * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current + * cable detection and then we are able to read C_DET[3:0]. + * + * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 + * Microcode Default Value' section below. + */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, + scsi_cfg1 | DIS_TERM_DRV); + + /* + * If the PCI Configuration Command Register "Parity Error Response + * Control" Bit was clear (0), then set the microcode variable + * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode + * to ignore DMA parity errors. + */ + if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_IGNORE_PERR; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - /* - * Build the carrier freelist. - * - * Driver must have already allocated memory and set 'carrier_buf'. - */ - - ASC_ASSERT(asc_dvc->carrier_buf != NULL); - - carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); - asc_dvc->carr_freelist = NULL; - if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) - { - buf_size = ADV_CARRIER_BUFSIZE; - } else - { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); - } + /* + * If the BIOS control flag AIPP (Asynchronous Information + * Phase Protection) disable bit is not set, then set the firmware + * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable + * AIPP checking and encoding. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_ENABLE_AIPP; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - do { - /* - * Get physical address for the carrier 'carrp'. - */ - contig_len = sizeof(ADV_CARR_T); - carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL, (uchar *) carrp, - (ADV_SDCNT *) &contig_len, ADV_IS_CARRIER_FLAG)); - - buf_size -= sizeof(ADV_CARR_T); - - /* - * If the current carrier is not physically contiguous, then - * maybe there was a page crossing. Try the next carrier aligned - * start address. - */ - if (contig_len < sizeof(ADV_CARR_T)) - { - carrp++; - continue; - } - - carrp->carr_pa = carr_paddr; - carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - - /* - * Insert the carrier at the beginning of the freelist. - */ - carrp->next_vpa = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = carrp; - - carrp++; - } - while (buf_size > 0); + /* + * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4], + * and START_CTL_TH [3:2]. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM); + + /* + * Microcode operating variables for WDTR, SDTR, and command tag + * queuing will be set in AdvInquiryHandling() based on what a + * device reports it is capable of in Inquiry byte 7. + * + * If SCSI Bus Resets have been disabled, then directly set + * SDTR and WDTR from the EEPROM configuration. This will allow + * the BIOS and warm boot to work without a SCSI bus hang on + * the Inquiry caused by host and target mismatched DTR values. + * Without the SCSI Bus Reset, before an Inquiry a device can't + * be assumed to be in Asynchronous, Narrow mode. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + asc_dvc->wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + asc_dvc->sdtr_able); + } - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + /* + * Set microcode operating variables for DISC and SDTR_SPEED1, + * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM + * configuration values. + * + * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them + * without determining here whether the device supports SDTR. + */ + AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, + asc_dvc->cfg->disc_enable); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); + + /* + * Set SCSI_CFG0 Microcode Default Value. + * + * The microcode will set the SCSI_CFG0 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, + PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | + asc_dvc->chip_scsi_id); + + /* + * Calculate SCSI_CFG1 Microcode Default Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + * + * Each ASC-38C1600 function has only two cable detect bits. + * The bus mode override bits are in IOPB_SOFT_OVER_WR. + */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + + /* + * If the cable is reversed all of the SCSI_CTRL register signals + * will be set. Check for and return an error if this condition is + * found. + */ + if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { + asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; + return ADV_ERROR; + } - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + /* + * Each ASC-38C1600 function has two connectors. Only an HVD device + * can not be connected to either connector. An LVD device or SE device + * may be connected to either connecor. If an SE device is connected, + * then at most Ultra speed (20 Mhz) can be used on both connectors. + * + * If an HVD device is attached, return an error. + */ + if (scsi_cfg1 & HVD) { + asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; + return ADV_ERROR; + } - /* - * Set RISC ICQ physical address start value. Initialize the - * COMMA register to the same value otherwise the RISC will - * prematurely detect a command is available. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); - AdvWriteDWordRegister(iop_base, IOPDW_COMMA, - le32_to_cpu(asc_dvc->icq_sp->carr_pa)); + /* + * Each function in the ASC-38C1600 uses only the SE cable detect and + * termination because there are two connectors for each function. Each + * function may use either LVD or SE mode. Corresponding the SE automatic + * termination control EEPROM bits are used for each function. Each + * function has its own EEPROM. If SE automatic control is enabled for + * the function, then set the termination value based on a table listed + * in a_condor.h. + * + * If manual termination is specified in the EEPROM for the function, + * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is + * ready to be 'ored' into SCSI_CFG1. + */ + if ((asc_dvc->cfg->termination & TERM_SE) == 0) { + /* SE automatic termination control is enabled. */ + switch (scsi_cfg1 & C_DET_SE) { + /* TERM_SE_HI: on, TERM_SE_LO: on */ + case 0x1: + case 0x2: + case 0x3: + asc_dvc->cfg->termination |= TERM_SE; + break; + + case 0x0: + if (ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) == 0) { + /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */ + } else { + /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */ + asc_dvc->cfg->termination |= TERM_SE_HI; + } + break; + } + } - /* - * Set-up the RISC->Host Initiator Response Queue (IRQ). - */ - if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) - { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + /* + * Clear any set TERM_SE bits. + */ + scsi_cfg1 &= ~TERM_SE; + + /* + * Invert the TERM_SE bits and then set 'scsi_cfg1'. + */ + scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE); + + /* + * Clear Big Endian and Terminator Polarity bits and set possibly + * modified termination control bits in the Microcode SCSI_CFG1 + * Register Value. + * + * Big Endian bit is not used even on big endian machines. + */ + scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL); + + /* + * Set SCSI_CFG1 Microcode Default Value + * + * Set possibly modified termination control bits in the Microcode + * SCSI_CFG1 Register Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); + + /* + * Set MEM_CFG Microcode Default Value + * + * The microcode will set the MEM_CFG register using this value + * after it is started below. + * + * MEM_CFG may be accessed as a word or byte, but only bits 0-7 + * are defined. + * + * ASC-38C1600 has 32KB internal memory. + * + * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come + * out a special 16K Adv Library and Microcode version. After the issue + * resolved, we should turn back to the 32K support. Both a_condor.h and + * mcode.sas files also need to be updated. + * + * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + * BIOS_EN | RAM_SZ_32KB); + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + BIOS_EN | RAM_SZ_16KB); + + /* + * Set SEL_MASK Microcode Default Value + * + * The microcode will set the SEL_MASK register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, + ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + + /* + * Build the carrier freelist. + * + * Driver must have already allocated memory and set 'carrier_buf'. + */ + + ASC_ASSERT(asc_dvc->carrier_buf != NULL); + + carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); + asc_dvc->carr_freelist = NULL; + if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) { + buf_size = ADV_CARRIER_BUFSIZE; + } else { + buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); + } - /* - * The first command completed by the RISC will be placed in - * the stopper. - * - * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is - * completed the RISC will set the ASC_RQ_STOPPER bit. - */ - asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + do { + /* + * Get physical address for the carrier 'carrp'. + */ + contig_len = sizeof(ADV_CARR_T); + carr_paddr = + cpu_to_le32(DvcGetPhyAddr + (asc_dvc, NULL, (uchar *)carrp, + (ADV_SDCNT *)&contig_len, + ADV_IS_CARRIER_FLAG)); - /* - * Set RISC IRQ physical address start value. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); - asc_dvc->carr_pending_cnt = 0; + buf_size -= sizeof(ADV_CARR_T); - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR)); - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); + /* + * If the current carrier is not physically contiguous, then + * maybe there was a page crossing. Try the next carrier aligned + * start address. + */ + if (contig_len < sizeof(ADV_CARR_T)) { + carrp++; + continue; + } + + carrp->carr_pa = carr_paddr; + carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + /* + * Insert the carrier at the beginning of the freelist. + */ + carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = carrp; - /* - * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus - * Resets should be performed. The RISC has to be running - * to issue a SCSI Bus Reset. - */ - if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) - { - /* - * If the BIOS Signature is present in memory, restore the - * per TID microcode operating variables. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM)/2] == 0x55AA) - { - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ASC_MAX_TID; tid++) - { - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - } else - { - if (AdvResetSB(asc_dvc) != ADV_TRUE) - { - warn_code = ASC_WARN_BUSRESET_ERROR; - } - } - } + carrp++; + } + while (buf_size > 0); + + /* + * Set-up the Host->RISC Initiator Command Queue (ICQ). + */ + if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + + /* + * The first command issued will be placed in the stopper carrier. + */ + asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC ICQ physical address start value. Initialize the + * COMMA register to the same value otherwise the RISC will + * prematurely detect a command is available. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + AdvWriteDWordRegister(iop_base, IOPDW_COMMA, + le32_to_cpu(asc_dvc->icq_sp->carr_pa)); + + /* + * Set-up the RISC->Host Initiator Response Queue (IRQ). + */ + if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + + /* + * The first command completed by the RISC will be placed in + * the stopper. + * + * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is + * completed the RISC will set the ASC_RQ_STOPPER bit. + */ + asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC IRQ physical address start value. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); + asc_dvc->carr_pending_cnt = 0; + + AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, + (ADV_INTR_ENABLE_HOST_INTR | + ADV_INTR_ENABLE_GLOBAL_INTR)); + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); + AdvWriteWordRegister(iop_base, IOPW_PC, word); + + /* finally, finally, gentlemen, start your engine */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + + /* + * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus + * Resets should be performed. The RISC has to be running + * to issue a SCSI Bus Reset. + */ + if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { + /* + * If the BIOS Signature is present in memory, restore the + * per TID microcode operating variables. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == + 0x55AA) { + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + tagqng_able); + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + } else { + if (AdvResetSB(asc_dvc) != ADV_TRUE) { + warn_code = ASC_WARN_BUSRESET_ERROR; + } + } + } - return warn_code; + return warn_code; } /* @@ -16378,164 +16135,146 @@ AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) * * Note: Chip is stopped on entry. */ -STATIC int __init -AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) +static int __init AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADVEEP_3550_CONFIG eep_config; - int i; + AdvPortAddr iop_base; + ushort warn_code; + ADVEEP_3550_CONFIG eep_config; + int i; - iop_base = asc_dvc->iop_base; + iop_base = asc_dvc->iop_base; - warn_code = 0; + warn_code = 0; - /* - * Read the board's EEPROM configuration. - * - * Set default values if a bad checksum is found. - */ - if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) - { - warn_code |= ASC_WARN_EEPROM_CHKSUM; - - /* - * Set EEPROM default values. - */ - for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) - { - *((uchar *) &eep_config + i) = - *((uchar *) &Default_3550_EEPROM_Config + i); - } - - /* - * Assume the 6 byte board serial number that was read - * from EEPROM is correct even if the EEPROM checksum - * failed. - */ - eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - - eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - - eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - - AdvSet3550EEPConfig(iop_base, &eep_config); - } - /* - * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the - * EEPROM configuration that was read. - * - * This is the mapping of EEPROM fields to Adv Library fields. - */ - asc_dvc->wdtr_able = eep_config.wdtr_able; - asc_dvc->sdtr_able = eep_config.sdtr_able; - asc_dvc->ultra_able = eep_config.ultra_able; - asc_dvc->tagqng_able = eep_config.tagqng_able; - asc_dvc->cfg->disc_enable = eep_config.disc_enable; - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; - asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); - asc_dvc->start_motor = eep_config.start_motor; - asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; - asc_dvc->bios_ctrl = eep_config.bios_ctrl; - asc_dvc->no_scam = eep_config.scam_tolerant; - asc_dvc->cfg->serial1 = eep_config.serial_number_word1; - asc_dvc->cfg->serial2 = eep_config.serial_number_word2; - asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + /* + * Read the board's EEPROM configuration. + * + * Set default values if a bad checksum is found. + */ + if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) { + warn_code |= ASC_WARN_EEPROM_CHKSUM; - /* - * Set the host maximum queuing (max. 253, min. 16) and the per device - * maximum queuing (max. 63, min. 4). - */ - if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_host_qng == 0) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else - { - eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; - } - } + /* + * Set EEPROM default values. + */ + for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) { + *((uchar *)&eep_config + i) = + *((uchar *)&Default_3550_EEPROM_Config + i); + } - if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_dvc_qng == 0) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else - { - eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; - } - } + /* + * Assume the 6 byte board serial number that was read + * from EEPROM is correct even if the EEPROM checksum + * failed. + */ + eep_config.serial_number_word3 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - /* - * If 'max_dvc_qng' is greater than 'max_host_qng', then - * set 'max_dvc_qng' to 'max_host_qng'. - */ - if (eep_config.max_dvc_qng > eep_config.max_host_qng) - { - eep_config.max_dvc_qng = eep_config.max_host_qng; - } + eep_config.serial_number_word2 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - /* - * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' - * values based on possibly adjusted EEPROM values. - */ - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + eep_config.serial_number_word1 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); + + AdvSet3550EEPConfig(iop_base, &eep_config); + } + /* + * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the + * EEPROM configuration that was read. + * + * This is the mapping of EEPROM fields to Adv Library fields. + */ + asc_dvc->wdtr_able = eep_config.wdtr_able; + asc_dvc->sdtr_able = eep_config.sdtr_able; + asc_dvc->ultra_able = eep_config.ultra_able; + asc_dvc->tagqng_able = eep_config.tagqng_able; + asc_dvc->cfg->disc_enable = eep_config.disc_enable; + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); + asc_dvc->start_motor = eep_config.start_motor; + asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; + asc_dvc->bios_ctrl = eep_config.bios_ctrl; + asc_dvc->no_scam = eep_config.scam_tolerant; + asc_dvc->cfg->serial1 = eep_config.serial_number_word1; + asc_dvc->cfg->serial2 = eep_config.serial_number_word2; + asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + + /* + * Set the host maximum queuing (max. 253, min. 16) and the per device + * maximum queuing (max. 63, min. 4). + */ + if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_host_qng == 0) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else { + eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; + } + } + if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_dvc_qng == 0) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else { + eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; + } + } - /* - * If the EEPROM 'termination' field is set to automatic (0), then set - * the ADV_DVC_CFG 'termination' field to automatic also. - * - * If the termination is specified with a non-zero 'termination' - * value check that a legal value is set and set the ADV_DVC_CFG - * 'termination' field appropriately. - */ - if (eep_config.termination == 0) - { - asc_dvc->cfg->termination = 0; /* auto termination */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination == 1) - { - asc_dvc->cfg->termination = TERM_CTL_SEL; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination == 2) - { - asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination == 3) - { - asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L; - } else - { - /* - * The EEPROM 'termination' field contains a bad value. Use - * automatic termination instead. - */ - asc_dvc->cfg->termination = 0; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + /* + * If 'max_dvc_qng' is greater than 'max_host_qng', then + * set 'max_dvc_qng' to 'max_host_qng'. + */ + if (eep_config.max_dvc_qng > eep_config.max_host_qng) { + eep_config.max_dvc_qng = eep_config.max_host_qng; + } - return warn_code; + /* + * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' + * values based on possibly adjusted EEPROM values. + */ + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + + /* + * If the EEPROM 'termination' field is set to automatic (0), then set + * the ADV_DVC_CFG 'termination' field to automatic also. + * + * If the termination is specified with a non-zero 'termination' + * value check that a legal value is set and set the ADV_DVC_CFG + * 'termination' field appropriately. + */ + if (eep_config.termination == 0) { + asc_dvc->cfg->termination = 0; /* auto termination */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination == 1) { + asc_dvc->cfg->termination = TERM_CTL_SEL; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination == 2) { + asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination == 3) { + asc_dvc->cfg->termination = + TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L; + } else { + /* + * The EEPROM 'termination' field contains a bad value. Use + * automatic termination instead. + */ + asc_dvc->cfg->termination = 0; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } + + return warn_code; } /* @@ -16550,225 +16289,195 @@ AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) * * Note: Chip is stopped on entry. */ -STATIC int __init -AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) +static int __init AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADVEEP_38C0800_CONFIG eep_config; - int i; - uchar tid, termination; - ushort sdtr_speed = 0; + AdvPortAddr iop_base; + ushort warn_code; + ADVEEP_38C0800_CONFIG eep_config; + int i; + uchar tid, termination; + ushort sdtr_speed = 0; + + iop_base = asc_dvc->iop_base; + + warn_code = 0; + + /* + * Read the board's EEPROM configuration. + * + * Set default values if a bad checksum is found. + */ + if (AdvGet38C0800EEPConfig(iop_base, &eep_config) != + eep_config.check_sum) { + warn_code |= ASC_WARN_EEPROM_CHKSUM; - iop_base = asc_dvc->iop_base; + /* + * Set EEPROM default values. + */ + for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) { + *((uchar *)&eep_config + i) = + *((uchar *)&Default_38C0800_EEPROM_Config + i); + } - warn_code = 0; + /* + * Assume the 6 byte board serial number that was read + * from EEPROM is correct even if the EEPROM checksum + * failed. + */ + eep_config.serial_number_word3 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - /* - * Read the board's EEPROM configuration. - * - * Set default values if a bad checksum is found. - */ - if (AdvGet38C0800EEPConfig(iop_base, &eep_config) != eep_config.check_sum) - { - warn_code |= ASC_WARN_EEPROM_CHKSUM; - - /* - * Set EEPROM default values. - */ - for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) - { - *((uchar *) &eep_config + i) = - *((uchar *) &Default_38C0800_EEPROM_Config + i); - } - - /* - * Assume the 6 byte board serial number that was read - * from EEPROM is correct even if the EEPROM checksum - * failed. - */ - eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - - eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - - eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - - AdvSet38C0800EEPConfig(iop_base, &eep_config); - } - /* - * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the - * EEPROM configuration that was read. - * - * This is the mapping of EEPROM fields to Adv Library fields. - */ - asc_dvc->wdtr_able = eep_config.wdtr_able; - asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; - asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; - asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; - asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; - asc_dvc->tagqng_able = eep_config.tagqng_able; - asc_dvc->cfg->disc_enable = eep_config.disc_enable; - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; - asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); - asc_dvc->start_motor = eep_config.start_motor; - asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; - asc_dvc->bios_ctrl = eep_config.bios_ctrl; - asc_dvc->no_scam = eep_config.scam_tolerant; - asc_dvc->cfg->serial1 = eep_config.serial_number_word1; - asc_dvc->cfg->serial2 = eep_config.serial_number_word2; - asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + eep_config.serial_number_word2 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - /* - * For every Target ID if any of its 'sdtr_speed[1234]' bits - * are set, then set an 'sdtr_able' bit for it. - */ - asc_dvc->sdtr_able = 0; - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - if (tid == 0) - { - sdtr_speed = asc_dvc->sdtr_speed1; - } else if (tid == 4) - { - sdtr_speed = asc_dvc->sdtr_speed2; - } else if (tid == 8) - { - sdtr_speed = asc_dvc->sdtr_speed3; - } else if (tid == 12) - { - sdtr_speed = asc_dvc->sdtr_speed4; - } - if (sdtr_speed & ADV_MAX_TID) - { - asc_dvc->sdtr_able |= (1 << tid); - } - sdtr_speed >>= 4; - } + eep_config.serial_number_word1 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - /* - * Set the host maximum queuing (max. 253, min. 16) and the per device - * maximum queuing (max. 63, min. 4). - */ - if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_host_qng == 0) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else - { - eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; - } - } + AdvSet38C0800EEPConfig(iop_base, &eep_config); + } + /* + * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the + * EEPROM configuration that was read. + * + * This is the mapping of EEPROM fields to Adv Library fields. + */ + asc_dvc->wdtr_able = eep_config.wdtr_able; + asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; + asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; + asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; + asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; + asc_dvc->tagqng_able = eep_config.tagqng_able; + asc_dvc->cfg->disc_enable = eep_config.disc_enable; + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); + asc_dvc->start_motor = eep_config.start_motor; + asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; + asc_dvc->bios_ctrl = eep_config.bios_ctrl; + asc_dvc->no_scam = eep_config.scam_tolerant; + asc_dvc->cfg->serial1 = eep_config.serial_number_word1; + asc_dvc->cfg->serial2 = eep_config.serial_number_word2; + asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + + /* + * For every Target ID if any of its 'sdtr_speed[1234]' bits + * are set, then set an 'sdtr_able' bit for it. + */ + asc_dvc->sdtr_able = 0; + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + if (tid == 0) { + sdtr_speed = asc_dvc->sdtr_speed1; + } else if (tid == 4) { + sdtr_speed = asc_dvc->sdtr_speed2; + } else if (tid == 8) { + sdtr_speed = asc_dvc->sdtr_speed3; + } else if (tid == 12) { + sdtr_speed = asc_dvc->sdtr_speed4; + } + if (sdtr_speed & ADV_MAX_TID) { + asc_dvc->sdtr_able |= (1 << tid); + } + sdtr_speed >>= 4; + } - if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_dvc_qng == 0) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else - { - eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; - } - } + /* + * Set the host maximum queuing (max. 253, min. 16) and the per device + * maximum queuing (max. 63, min. 4). + */ + if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_host_qng == 0) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else { + eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; + } + } - /* - * If 'max_dvc_qng' is greater than 'max_host_qng', then - * set 'max_dvc_qng' to 'max_host_qng'. - */ - if (eep_config.max_dvc_qng > eep_config.max_host_qng) - { - eep_config.max_dvc_qng = eep_config.max_host_qng; - } + if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_dvc_qng == 0) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else { + eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; + } + } - /* - * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' - * values based on possibly adjusted EEPROM values. - */ - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + /* + * If 'max_dvc_qng' is greater than 'max_host_qng', then + * set 'max_dvc_qng' to 'max_host_qng'. + */ + if (eep_config.max_dvc_qng > eep_config.max_host_qng) { + eep_config.max_dvc_qng = eep_config.max_host_qng; + } - /* - * If the EEPROM 'termination' field is set to automatic (0), then set - * the ADV_DVC_CFG 'termination' field to automatic also. - * - * If the termination is specified with a non-zero 'termination' - * value check that a legal value is set and set the ADV_DVC_CFG - * 'termination' field appropriately. - */ - if (eep_config.termination_se == 0) - { - termination = 0; /* auto termination for SE */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_se == 1) - { - termination = 0; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_se == 2) - { - termination = TERM_SE_HI; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_se == 3) - { - termination = TERM_SE; - } else - { - /* - * The EEPROM 'termination_se' field contains a bad value. - * Use automatic termination instead. - */ - termination = 0; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + /* + * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' + * values based on possibly adjusted EEPROM values. + */ + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + + /* + * If the EEPROM 'termination' field is set to automatic (0), then set + * the ADV_DVC_CFG 'termination' field to automatic also. + * + * If the termination is specified with a non-zero 'termination' + * value check that a legal value is set and set the ADV_DVC_CFG + * 'termination' field appropriately. + */ + if (eep_config.termination_se == 0) { + termination = 0; /* auto termination for SE */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_se == 1) { + termination = 0; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_se == 2) { + termination = TERM_SE_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_se == 3) { + termination = TERM_SE; + } else { + /* + * The EEPROM 'termination_se' field contains a bad value. + * Use automatic termination instead. + */ + termination = 0; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } - if (eep_config.termination_lvd == 0) - { - asc_dvc->cfg->termination = termination; /* auto termination for LVD */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_lvd == 1) - { - asc_dvc->cfg->termination = termination; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_lvd == 2) - { - asc_dvc->cfg->termination = termination | TERM_LVD_HI; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_lvd == 3) - { - asc_dvc->cfg->termination = - termination | TERM_LVD; - } else - { - /* - * The EEPROM 'termination_lvd' field contains a bad value. - * Use automatic termination instead. - */ - asc_dvc->cfg->termination = termination; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + if (eep_config.termination_lvd == 0) { + asc_dvc->cfg->termination = termination; /* auto termination for LVD */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_lvd == 1) { + asc_dvc->cfg->termination = termination; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_lvd == 2) { + asc_dvc->cfg->termination = termination | TERM_LVD_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_lvd == 3) { + asc_dvc->cfg->termination = termination | TERM_LVD; + } else { + /* + * The EEPROM 'termination_lvd' field contains a bad value. + * Use automatic termination instead. + */ + asc_dvc->cfg->termination = termination; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } - return warn_code; + return warn_code; } /* @@ -16783,265 +16492,240 @@ AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) * * Note: Chip is stopped on entry. */ -STATIC int __init -AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) +static int __init AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ushort warn_code; - ADVEEP_38C1600_CONFIG eep_config; - int i; - uchar tid, termination; - ushort sdtr_speed = 0; + AdvPortAddr iop_base; + ushort warn_code; + ADVEEP_38C1600_CONFIG eep_config; + int i; + uchar tid, termination; + ushort sdtr_speed = 0; + + iop_base = asc_dvc->iop_base; + + warn_code = 0; + + /* + * Read the board's EEPROM configuration. + * + * Set default values if a bad checksum is found. + */ + if (AdvGet38C1600EEPConfig(iop_base, &eep_config) != + eep_config.check_sum) { + warn_code |= ASC_WARN_EEPROM_CHKSUM; - iop_base = asc_dvc->iop_base; + /* + * Set EEPROM default values. + */ + for (i = 0; i < sizeof(ADVEEP_38C1600_CONFIG); i++) { + if (i == 1 + && ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) != + 0) { + /* + * Set Function 1 EEPROM Word 0 MSB + * + * Clear the BIOS_ENABLE (bit 14) and INTAB (bit 11) + * EEPROM bits. + * + * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 and + * old Mac system booting problem. The Expansion ROM must + * be disabled in Function 1 for these systems. + * + */ + *((uchar *)&eep_config + i) = + ((* + ((uchar *)&Default_38C1600_EEPROM_Config + + + i)) & + (~ + (((ADV_EEPROM_BIOS_ENABLE | + ADV_EEPROM_INTAB) >> 8) & 0xFF))); + + /* + * Set the INTAB (bit 11) if the GPIO 0 input indicates + * the Function 1 interrupt line is wired to INTA. + * + * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input: + * 1 - Function 1 interrupt line wired to INT A. + * 0 - Function 1 interrupt line wired to INT B. + * + * Note: Adapter boards always have Function 0 wired to INTA. + * Put all 5 GPIO bits in input mode and then read + * their input values. + */ + AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, + 0); + if (AdvReadByteRegister + (iop_base, IOPB_GPIO_DATA) & 0x01) { + /* Function 1 interrupt wired to INTA; Set EEPROM bit. */ + *((uchar *)&eep_config + i) |= + ((ADV_EEPROM_INTAB >> 8) & 0xFF); + } + } else { + *((uchar *)&eep_config + i) = + *((uchar *)&Default_38C1600_EEPROM_Config + + i); + } + } - warn_code = 0; + /* + * Assume the 6 byte board serial number that was read + * from EEPROM is correct even if the EEPROM checksum + * failed. + */ + eep_config.serial_number_word3 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - /* - * Read the board's EEPROM configuration. - * - * Set default values if a bad checksum is found. - */ - if (AdvGet38C1600EEPConfig(iop_base, &eep_config) != eep_config.check_sum) - { - warn_code |= ASC_WARN_EEPROM_CHKSUM; - - /* - * Set EEPROM default values. - */ - for (i = 0; i < sizeof(ADVEEP_38C1600_CONFIG); i++) - { - if (i == 1 && ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) != 0) - { - /* - * Set Function 1 EEPROM Word 0 MSB - * - * Clear the BIOS_ENABLE (bit 14) and INTAB (bit 11) - * EEPROM bits. - * - * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 and - * old Mac system booting problem. The Expansion ROM must - * be disabled in Function 1 for these systems. - * - */ - *((uchar *) &eep_config + i) = - ((*((uchar *) &Default_38C1600_EEPROM_Config + i)) & - (~(((ADV_EEPROM_BIOS_ENABLE | ADV_EEPROM_INTAB) >> 8) & - 0xFF))); - - /* - * Set the INTAB (bit 11) if the GPIO 0 input indicates - * the Function 1 interrupt line is wired to INTA. - * - * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input: - * 1 - Function 1 interrupt line wired to INT A. - * 0 - Function 1 interrupt line wired to INT B. - * - * Note: Adapter boards always have Function 0 wired to INTA. - * Put all 5 GPIO bits in input mode and then read - * their input values. - */ - AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0); - if (AdvReadByteRegister(iop_base, IOPB_GPIO_DATA) & 0x01) - { - /* Function 1 interrupt wired to INTA; Set EEPROM bit. */ - *((uchar *) &eep_config + i) |= - ((ADV_EEPROM_INTAB >> 8) & 0xFF); - } - } - else - { - *((uchar *) &eep_config + i) = - *((uchar *) &Default_38C1600_EEPROM_Config + i); - } - } - - /* - * Assume the 6 byte board serial number that was read - * from EEPROM is correct even if the EEPROM checksum - * failed. - */ - eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - - eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - - eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - - AdvSet38C1600EEPConfig(iop_base, &eep_config); - } + eep_config.serial_number_word2 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - /* - * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the - * EEPROM configuration that was read. - * - * This is the mapping of EEPROM fields to Adv Library fields. - */ - asc_dvc->wdtr_able = eep_config.wdtr_able; - asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; - asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; - asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; - asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; - asc_dvc->ppr_able = 0; - asc_dvc->tagqng_able = eep_config.tagqng_able; - asc_dvc->cfg->disc_enable = eep_config.disc_enable; - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; - asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID); - asc_dvc->start_motor = eep_config.start_motor; - asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; - asc_dvc->bios_ctrl = eep_config.bios_ctrl; - asc_dvc->no_scam = eep_config.scam_tolerant; + eep_config.serial_number_word1 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - /* - * For every Target ID if any of its 'sdtr_speed[1234]' bits - * are set, then set an 'sdtr_able' bit for it. - */ - asc_dvc->sdtr_able = 0; - for (tid = 0; tid <= ASC_MAX_TID; tid++) - { - if (tid == 0) - { - sdtr_speed = asc_dvc->sdtr_speed1; - } else if (tid == 4) - { - sdtr_speed = asc_dvc->sdtr_speed2; - } else if (tid == 8) - { - sdtr_speed = asc_dvc->sdtr_speed3; - } else if (tid == 12) - { - sdtr_speed = asc_dvc->sdtr_speed4; - } - if (sdtr_speed & ASC_MAX_TID) - { - asc_dvc->sdtr_able |= (1 << tid); - } - sdtr_speed >>= 4; - } + AdvSet38C1600EEPConfig(iop_base, &eep_config); + } - /* - * Set the host maximum queuing (max. 253, min. 16) and the per device - * maximum queuing (max. 63, min. 4). - */ - if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_host_qng == 0) - { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else - { - eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; - } - } + /* + * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the + * EEPROM configuration that was read. + * + * This is the mapping of EEPROM fields to Adv Library fields. + */ + asc_dvc->wdtr_able = eep_config.wdtr_able; + asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; + asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; + asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; + asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; + asc_dvc->ppr_able = 0; + asc_dvc->tagqng_able = eep_config.tagqng_able; + asc_dvc->cfg->disc_enable = eep_config.disc_enable; + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID); + asc_dvc->start_motor = eep_config.start_motor; + asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; + asc_dvc->bios_ctrl = eep_config.bios_ctrl; + asc_dvc->no_scam = eep_config.scam_tolerant; + + /* + * For every Target ID if any of its 'sdtr_speed[1234]' bits + * are set, then set an 'sdtr_able' bit for it. + */ + asc_dvc->sdtr_able = 0; + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + if (tid == 0) { + sdtr_speed = asc_dvc->sdtr_speed1; + } else if (tid == 4) { + sdtr_speed = asc_dvc->sdtr_speed2; + } else if (tid == 8) { + sdtr_speed = asc_dvc->sdtr_speed3; + } else if (tid == 12) { + sdtr_speed = asc_dvc->sdtr_speed4; + } + if (sdtr_speed & ASC_MAX_TID) { + asc_dvc->sdtr_able |= (1 << tid); + } + sdtr_speed >>= 4; + } - if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) - { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_dvc_qng == 0) - { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else - { - eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; - } - } + /* + * Set the host maximum queuing (max. 253, min. 16) and the per device + * maximum queuing (max. 63, min. 4). + */ + if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_host_qng == 0) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else { + eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; + } + } - /* - * If 'max_dvc_qng' is greater than 'max_host_qng', then - * set 'max_dvc_qng' to 'max_host_qng'. - */ - if (eep_config.max_dvc_qng > eep_config.max_host_qng) - { - eep_config.max_dvc_qng = eep_config.max_host_qng; - } + if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_dvc_qng == 0) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else { + eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; + } + } - /* - * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng' - * values based on possibly adjusted EEPROM values. - */ - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + /* + * If 'max_dvc_qng' is greater than 'max_host_qng', then + * set 'max_dvc_qng' to 'max_host_qng'. + */ + if (eep_config.max_dvc_qng > eep_config.max_host_qng) { + eep_config.max_dvc_qng = eep_config.max_host_qng; + } - /* - * If the EEPROM 'termination' field is set to automatic (0), then set - * the ASC_DVC_CFG 'termination' field to automatic also. - * - * If the termination is specified with a non-zero 'termination' - * value check that a legal value is set and set the ASC_DVC_CFG - * 'termination' field appropriately. - */ - if (eep_config.termination_se == 0) - { - termination = 0; /* auto termination for SE */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_se == 1) - { - termination = 0; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_se == 2) - { - termination = TERM_SE_HI; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_se == 3) - { - termination = TERM_SE; - } else - { - /* - * The EEPROM 'termination_se' field contains a bad value. - * Use automatic termination instead. - */ - termination = 0; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + /* + * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng' + * values based on possibly adjusted EEPROM values. + */ + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + + /* + * If the EEPROM 'termination' field is set to automatic (0), then set + * the ASC_DVC_CFG 'termination' field to automatic also. + * + * If the termination is specified with a non-zero 'termination' + * value check that a legal value is set and set the ASC_DVC_CFG + * 'termination' field appropriately. + */ + if (eep_config.termination_se == 0) { + termination = 0; /* auto termination for SE */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_se == 1) { + termination = 0; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_se == 2) { + termination = TERM_SE_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_se == 3) { + termination = TERM_SE; + } else { + /* + * The EEPROM 'termination_se' field contains a bad value. + * Use automatic termination instead. + */ + termination = 0; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } - if (eep_config.termination_lvd == 0) - { - asc_dvc->cfg->termination = termination; /* auto termination for LVD */ - } else - { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_lvd == 1) - { - asc_dvc->cfg->termination = termination; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_lvd == 2) - { - asc_dvc->cfg->termination = termination | TERM_LVD_HI; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_lvd == 3) - { - asc_dvc->cfg->termination = - termination | TERM_LVD; - } else - { - /* - * The EEPROM 'termination_lvd' field contains a bad value. - * Use automatic termination instead. - */ - asc_dvc->cfg->termination = termination; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } + if (eep_config.termination_lvd == 0) { + asc_dvc->cfg->termination = termination; /* auto termination for LVD */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_lvd == 1) { + asc_dvc->cfg->termination = termination; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_lvd == 2) { + asc_dvc->cfg->termination = termination | TERM_LVD_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_lvd == 3) { + asc_dvc->cfg->termination = termination | TERM_LVD; + } else { + /* + * The EEPROM 'termination_lvd' field contains a bad value. + * Use automatic termination instead. + */ + asc_dvc->cfg->termination = termination; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } - return warn_code; + return warn_code; } /* @@ -17049,45 +16733,42 @@ AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) * * Return a checksum based on the EEPROM configuration read. */ -STATIC ushort __init +static ushort __init AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) { - ushort wval, chksum; - ushort *wbuf; - int eep_addr; - ushort *charfields; - - charfields = (ushort *) &ADVEEP_3550_Config_Field_IsChar; - wbuf = (ushort *) cfg_buf; - chksum = 0; - - for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; - eep_addr < ADV_EEP_DVC_CFG_END; - eep_addr++, wbuf++) - { - wval = AdvReadEEPWord(iop_base, eep_addr); - chksum += wval; /* Checksum is calculated from word values. */ - if (*charfields++) { - *wbuf = le16_to_cpu(wval); - } else { - *wbuf = wval; - } - } - /* Read checksum word. */ - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - wbuf++; charfields++; - - /* Read rest of EEPROM not covered by the checksum. */ - for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; - eep_addr < ADV_EEP_MAX_WORD_ADDR; - eep_addr++, wbuf++) - { - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - if (*charfields++) { - *wbuf = le16_to_cpu(*wbuf); - } - } - return chksum; + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; + + charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; + wbuf = (ushort *)cfg_buf; + chksum = 0; + + for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; + eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { + wval = AdvReadEEPWord(iop_base, eep_addr); + chksum += wval; /* Checksum is calculated from word values. */ + if (*charfields++) { + *wbuf = le16_to_cpu(wval); + } else { + *wbuf = wval; + } + } + /* Read checksum word. */ + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + wbuf++; + charfields++; + + /* Read rest of EEPROM not covered by the checksum. */ + for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; + eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + if (*charfields++) { + *wbuf = le16_to_cpu(*wbuf); + } + } + return chksum; } /* @@ -17095,46 +16776,42 @@ AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) * * Return a checksum based on the EEPROM configuration read. */ -STATIC ushort __init -AdvGet38C0800EEPConfig(AdvPortAddr iop_base, - ADVEEP_38C0800_CONFIG *cfg_buf) +static ushort __init +AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) { - ushort wval, chksum; - ushort *wbuf; - int eep_addr; - ushort *charfields; - - charfields = (ushort *) &ADVEEP_38C0800_Config_Field_IsChar; - wbuf = (ushort *) cfg_buf; - chksum = 0; - - for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; - eep_addr < ADV_EEP_DVC_CFG_END; - eep_addr++, wbuf++) - { - wval = AdvReadEEPWord(iop_base, eep_addr); - chksum += wval; /* Checksum is calculated from word values. */ - if (*charfields++) { - *wbuf = le16_to_cpu(wval); - } else { - *wbuf = wval; - } - } - /* Read checksum word. */ - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - wbuf++; charfields++; - - /* Read rest of EEPROM not covered by the checksum. */ - for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; - eep_addr < ADV_EEP_MAX_WORD_ADDR; - eep_addr++, wbuf++) - { - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - if (*charfields++) { - *wbuf = le16_to_cpu(*wbuf); - } - } - return chksum; + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; + + charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; + wbuf = (ushort *)cfg_buf; + chksum = 0; + + for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; + eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { + wval = AdvReadEEPWord(iop_base, eep_addr); + chksum += wval; /* Checksum is calculated from word values. */ + if (*charfields++) { + *wbuf = le16_to_cpu(wval); + } else { + *wbuf = wval; + } + } + /* Read checksum word. */ + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + wbuf++; + charfields++; + + /* Read rest of EEPROM not covered by the checksum. */ + for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; + eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + if (*charfields++) { + *wbuf = le16_to_cpu(*wbuf); + } + } + return chksum; } /* @@ -17142,81 +16819,74 @@ AdvGet38C0800EEPConfig(AdvPortAddr iop_base, * * Return a checksum based on the EEPROM configuration read. */ -STATIC ushort __init -AdvGet38C1600EEPConfig(AdvPortAddr iop_base, - ADVEEP_38C1600_CONFIG *cfg_buf) +static ushort __init +AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) { - ushort wval, chksum; - ushort *wbuf; - int eep_addr; - ushort *charfields; - - charfields = (ushort*) &ADVEEP_38C1600_Config_Field_IsChar; - wbuf = (ushort *) cfg_buf; - chksum = 0; - - for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; - eep_addr < ADV_EEP_DVC_CFG_END; - eep_addr++, wbuf++) - { - wval = AdvReadEEPWord(iop_base, eep_addr); - chksum += wval; /* Checksum is calculated from word values. */ - if (*charfields++) { - *wbuf = le16_to_cpu(wval); - } else { - *wbuf = wval; - } - } - /* Read checksum word. */ - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - wbuf++; charfields++; - - /* Read rest of EEPROM not covered by the checksum. */ - for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; - eep_addr < ADV_EEP_MAX_WORD_ADDR; - eep_addr++, wbuf++) - { - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - if (*charfields++) { - *wbuf = le16_to_cpu(*wbuf); - } - } - return chksum; + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; + + charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; + wbuf = (ushort *)cfg_buf; + chksum = 0; + + for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; + eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { + wval = AdvReadEEPWord(iop_base, eep_addr); + chksum += wval; /* Checksum is calculated from word values. */ + if (*charfields++) { + *wbuf = le16_to_cpu(wval); + } else { + *wbuf = wval; + } + } + /* Read checksum word. */ + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + wbuf++; + charfields++; + + /* Read rest of EEPROM not covered by the checksum. */ + for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; + eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + if (*charfields++) { + *wbuf = le16_to_cpu(*wbuf); + } + } + return chksum; } /* * Read the EEPROM from specified location */ -STATIC ushort __init -AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) +static ushort __init AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) { - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, - ASC_EEP_CMD_READ | eep_word_addr); - AdvWaitEEPCmd(iop_base); - return AdvReadWordRegister(iop_base, IOPW_EE_DATA); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_READ | eep_word_addr); + AdvWaitEEPCmd(iop_base); + return AdvReadWordRegister(iop_base, IOPW_EE_DATA); } /* * Wait for EEPROM command to complete */ -STATIC void __init -AdvWaitEEPCmd(AdvPortAddr iop_base) +static void __init AdvWaitEEPCmd(AdvPortAddr iop_base) { - int eep_delay_ms; - - for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) - { - if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) - { - break; - } - DvcSleepMilliSecond(1); - } - if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == 0) - { - ASC_ASSERT(0); - } - return; + int eep_delay_ms; + + for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) { + if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & + ASC_EEP_CMD_DONE) { + break; + } + DvcSleepMilliSecond(1); + } + if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == + 0) { + ASC_ASSERT(0); + } + return; } /* @@ -17225,201 +16895,202 @@ AdvWaitEEPCmd(AdvPortAddr iop_base) void __init AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) { - ushort *wbuf; - ushort addr, chksum; - ushort *charfields; - - wbuf = (ushort *) cfg_buf; - charfields = (ushort *) &ADVEEP_3550_Config_Field_IsChar; - chksum = 0; - - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); - AdvWaitEEPCmd(iop_base); - - /* - * Write EEPROM from word 0 to word 20. - */ - for (addr = ADV_EEP_DVC_CFG_BEGIN; - addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - chksum += *wbuf; /* Checksum is calculated from word values. */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - DvcSleepMilliSecond(ADV_EEP_DELAY_MS); - } - - /* - * Write EEPROM checksum at word 21. - */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - wbuf++; charfields++; + ushort *wbuf; + ushort addr, chksum; + ushort *charfields; + + wbuf = (ushort *)cfg_buf; + charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; + chksum = 0; + + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); + AdvWaitEEPCmd(iop_base); + + /* + * Write EEPROM from word 0 to word 20. + */ + for (addr = ADV_EEP_DVC_CFG_BEGIN; + addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + chksum += *wbuf; /* Checksum is calculated from word values. */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + DvcSleepMilliSecond(ADV_EEP_DELAY_MS); + } - /* - * Write EEPROM OEM name at words 22 to 29. - */ - for (addr = ADV_EEP_DVC_CTL_BEGIN; - addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - } - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); - AdvWaitEEPCmd(iop_base); - return; + /* + * Write EEPROM checksum at word 21. + */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + wbuf++; + charfields++; + + /* + * Write EEPROM OEM name at words 22 to 29. + */ + for (addr = ADV_EEP_DVC_CTL_BEGIN; + addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + } + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); + return; } /* * Write the EEPROM from 'cfg_buf'. */ void __init -AdvSet38C0800EEPConfig(AdvPortAddr iop_base, - ADVEEP_38C0800_CONFIG *cfg_buf) +AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) { - ushort *wbuf; - ushort *charfields; - ushort addr, chksum; - - wbuf = (ushort *) cfg_buf; - charfields = (ushort *) &ADVEEP_38C0800_Config_Field_IsChar; - chksum = 0; - - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); - AdvWaitEEPCmd(iop_base); - - /* - * Write EEPROM from word 0 to word 20. - */ - for (addr = ADV_EEP_DVC_CFG_BEGIN; - addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - chksum += *wbuf; /* Checksum is calculated from word values. */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - DvcSleepMilliSecond(ADV_EEP_DELAY_MS); - } - - /* - * Write EEPROM checksum at word 21. - */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - wbuf++; charfields++; + ushort *wbuf; + ushort *charfields; + ushort addr, chksum; + + wbuf = (ushort *)cfg_buf; + charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; + chksum = 0; + + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); + AdvWaitEEPCmd(iop_base); + + /* + * Write EEPROM from word 0 to word 20. + */ + for (addr = ADV_EEP_DVC_CFG_BEGIN; + addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + chksum += *wbuf; /* Checksum is calculated from word values. */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + DvcSleepMilliSecond(ADV_EEP_DELAY_MS); + } - /* - * Write EEPROM OEM name at words 22 to 29. - */ - for (addr = ADV_EEP_DVC_CTL_BEGIN; - addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - } - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); - AdvWaitEEPCmd(iop_base); - return; + /* + * Write EEPROM checksum at word 21. + */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + wbuf++; + charfields++; + + /* + * Write EEPROM OEM name at words 22 to 29. + */ + for (addr = ADV_EEP_DVC_CTL_BEGIN; + addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + } + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); + return; } /* * Write the EEPROM from 'cfg_buf'. */ void __init -AdvSet38C1600EEPConfig(AdvPortAddr iop_base, - ADVEEP_38C1600_CONFIG *cfg_buf) +AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) { - ushort *wbuf; - ushort *charfields; - ushort addr, chksum; - - wbuf = (ushort *) cfg_buf; - charfields = (ushort *) &ADVEEP_38C1600_Config_Field_IsChar; - chksum = 0; - - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); - AdvWaitEEPCmd(iop_base); - - /* - * Write EEPROM from word 0 to word 20. - */ - for (addr = ADV_EEP_DVC_CFG_BEGIN; - addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - chksum += *wbuf; /* Checksum is calculated from word values. */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - DvcSleepMilliSecond(ADV_EEP_DELAY_MS); - } - - /* - * Write EEPROM checksum at word 21. - */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - wbuf++; charfields++; + ushort *wbuf; + ushort *charfields; + ushort addr, chksum; + + wbuf = (ushort *)cfg_buf; + charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; + chksum = 0; + + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); + AdvWaitEEPCmd(iop_base); + + /* + * Write EEPROM from word 0 to word 20. + */ + for (addr = ADV_EEP_DVC_CFG_BEGIN; + addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + chksum += *wbuf; /* Checksum is calculated from word values. */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + DvcSleepMilliSecond(ADV_EEP_DELAY_MS); + } - /* - * Write EEPROM OEM name at words 22 to 29. - */ - for (addr = ADV_EEP_DVC_CTL_BEGIN; - addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) - { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - } - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); - AdvWaitEEPCmd(iop_base); - return; + /* + * Write EEPROM checksum at word 21. + */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + wbuf++; + charfields++; + + /* + * Write EEPROM OEM name at words 22 to 29. + */ + for (addr = ADV_EEP_DVC_CTL_BEGIN; + addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { + ushort word; + + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; + } + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + } + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); + return; } /* a_advlib.c */ @@ -17444,126 +17115,120 @@ AdvSet38C1600EEPConfig(AdvPortAddr iop_base, * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure * host IC error. */ -STATIC int -AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, - ADV_SCSI_REQ_Q *scsiq) +static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) { - ulong last_int_level; - AdvPortAddr iop_base; - ADV_DCNT req_size; - ADV_PADDR req_paddr; - ADV_CARR_T *new_carrp; - - ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */ - - /* - * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID. - */ - if (scsiq->target_id > ADV_MAX_TID) - { - scsiq->host_status = QHSTA_M_INVALID_DEVICE; - scsiq->done_status = QD_WITH_ERROR; - return ADV_ERROR; - } - - iop_base = asc_dvc->iop_base; - - last_int_level = DvcEnterCritical(); - - /* - * Allocate a carrier ensuring at least one carrier always - * remains on the freelist and initialize fields. - */ - if ((new_carrp = asc_dvc->carr_freelist) == NULL) - { - DvcLeaveCritical(last_int_level); - return ADV_BUSY; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa)); - asc_dvc->carr_pending_cnt++; - - /* - * Set the carrier to be a stopper by setting 'next_vpa' - * to the stopper value. The current stopper will be changed - * below to point to the new stopper. - */ - new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - - /* - * Clear the ADV_SCSI_REQ_Q done flag. - */ - scsiq->a_flag &= ~ADV_SCSIQ_DONE; - - req_size = sizeof(ADV_SCSI_REQ_Q); - req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *) scsiq, - (ADV_SDCNT *) &req_size, ADV_IS_SCSIQ_FLAG); - - ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr); - ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q)); - - /* Wait for assertion before making little-endian */ - req_paddr = cpu_to_le32(req_paddr); - - /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */ - scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq)); - scsiq->scsiq_rptr = req_paddr; + ulong last_int_level; + AdvPortAddr iop_base; + ADV_DCNT req_size; + ADV_PADDR req_paddr; + ADV_CARR_T *new_carrp; + + ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */ + + /* + * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID. + */ + if (scsiq->target_id > ADV_MAX_TID) { + scsiq->host_status = QHSTA_M_INVALID_DEVICE; + scsiq->done_status = QD_WITH_ERROR; + return ADV_ERROR; + } - scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp)); - /* - * Every ADV_CARR_T.carr_pa is byte swapped to little-endian - * order during initialization. - */ - scsiq->carr_pa = asc_dvc->icq_sp->carr_pa; - - /* - * Use the current stopper to send the ADV_SCSI_REQ_Q command to - * the microcode. The newly allocated stopper will become the new - * stopper. - */ - asc_dvc->icq_sp->areq_vpa = req_paddr; + iop_base = asc_dvc->iop_base; - /* - * Set the 'next_vpa' pointer for the old stopper to be the - * physical address of the new stopper. The RISC can only - * follow physical addresses. - */ - asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa; + last_int_level = DvcEnterCritical(); - /* - * Set the host adapter stopper pointer to point to the new carrier. - */ - asc_dvc->icq_sp = new_carrp; - - if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || - asc_dvc->chip_type == ADV_CHIP_ASC38C0800) - { - /* - * Tickle the RISC to tell it to read its Command Queue Head pointer. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); - if (asc_dvc->chip_type == ADV_CHIP_ASC3550) - { - /* - * Clear the tickle value. In the ASC-3550 the RISC flag - * command 'clr_tickle_a' does not work unless the host - * value is cleared. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); - } - } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - /* - * Notify the RISC a carrier is ready by writing the physical - * address of the new carrier stopper to the COMMA register. - */ - AdvWriteDWordRegister(iop_base, IOPDW_COMMA, - le32_to_cpu(new_carrp->carr_pa)); - } + /* + * Allocate a carrier ensuring at least one carrier always + * remains on the freelist and initialize fields. + */ + if ((new_carrp = asc_dvc->carr_freelist) == NULL) { + DvcLeaveCritical(last_int_level); + return ADV_BUSY; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa)); + asc_dvc->carr_pending_cnt++; + + /* + * Set the carrier to be a stopper by setting 'next_vpa' + * to the stopper value. The current stopper will be changed + * below to point to the new stopper. + */ + new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Clear the ADV_SCSI_REQ_Q done flag. + */ + scsiq->a_flag &= ~ADV_SCSIQ_DONE; + + req_size = sizeof(ADV_SCSI_REQ_Q); + req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq, + (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG); + + ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr); + ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q)); + + /* Wait for assertion before making little-endian */ + req_paddr = cpu_to_le32(req_paddr); + + /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */ + scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq)); + scsiq->scsiq_rptr = req_paddr; + + scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp)); + /* + * Every ADV_CARR_T.carr_pa is byte swapped to little-endian + * order during initialization. + */ + scsiq->carr_pa = asc_dvc->icq_sp->carr_pa; + + /* + * Use the current stopper to send the ADV_SCSI_REQ_Q command to + * the microcode. The newly allocated stopper will become the new + * stopper. + */ + asc_dvc->icq_sp->areq_vpa = req_paddr; + + /* + * Set the 'next_vpa' pointer for the old stopper to be the + * physical address of the new stopper. The RISC can only + * follow physical addresses. + */ + asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa; + + /* + * Set the host adapter stopper pointer to point to the new carrier. + */ + asc_dvc->icq_sp = new_carrp; + + if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || + asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + /* + * Tickle the RISC to tell it to read its Command Queue Head pointer. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { + /* + * Clear the tickle value. In the ASC-3550 the RISC flag + * command 'clr_tickle_a' does not work unless the host + * value is cleared. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, + ADV_TICKLE_NOP); + } + } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + /* + * Notify the RISC a carrier is ready by writing the physical + * address of the new carrier stopper to the COMMA register. + */ + AdvWriteDWordRegister(iop_base, IOPDW_COMMA, + le32_to_cpu(new_carrp->carr_pa)); + } - DvcLeaveCritical(last_int_level); + DvcLeaveCritical(last_int_level); - return ADV_SUCCESS; + return ADV_SUCCESS; } /* @@ -17575,42 +17240,39 @@ AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC * may be hung which requires driver recovery. */ -STATIC int -AdvResetSB(ADV_DVC_VAR *asc_dvc) +static int AdvResetSB(ADV_DVC_VAR *asc_dvc) { - int status; - - /* - * Send the SCSI Bus Reset idle start idle command which asserts - * the SCSI Bus Reset signal. - */ - status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET_START, 0L); - if (status != ADV_TRUE) - { - return status; - } - - /* - * Delay for the specified SCSI Bus Reset hold time. - * - * The hold time delay is done on the host because the RISC has no - * microsecond accurate timer. - */ - DvcDelayMicroSecond(asc_dvc, (ushort) ASC_SCSI_RESET_HOLD_TIME_US); + int status; + + /* + * Send the SCSI Bus Reset idle start idle command which asserts + * the SCSI Bus Reset signal. + */ + status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L); + if (status != ADV_TRUE) { + return status; + } - /* - * Send the SCSI Bus Reset end idle command which de-asserts - * the SCSI Bus Reset signal and purges any pending requests. - */ - status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET_END, 0L); - if (status != ADV_TRUE) - { - return status; - } + /* + * Delay for the specified SCSI Bus Reset hold time. + * + * The hold time delay is done on the host because the RISC has no + * microsecond accurate timer. + */ + DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US); + + /* + * Send the SCSI Bus Reset end idle command which de-asserts + * the SCSI Bus Reset signal and purges any pending requests. + */ + status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L); + if (status != ADV_TRUE) { + return status; + } - DvcSleepMilliSecond((ADV_DCNT) asc_dvc->scsi_reset_wait * 1000); + DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000); - return status; + return status; } /* @@ -17620,99 +17282,89 @@ AdvResetSB(ADV_DVC_VAR *asc_dvc) * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful. * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure. */ -STATIC int -AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) +static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) { - int status; - ushort wdtr_able, sdtr_able, tagqng_able; - ushort ppr_able = 0; - uchar tid, max_cmd[ADV_MAX_TID + 1]; - AdvPortAddr iop_base; - ushort bios_sig; - - iop_base = asc_dvc->iop_base; - - /* - * Save current per TID negotiated values. - */ - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - } - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * Force the AdvInitAsc3550/38C0800Driver() function to - * perform a SCSI Bus Reset by clearing the BIOS signature word. - * The initialization functions assumes a SCSI Bus Reset is not - * needed if the BIOS signature word is present. - */ - AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); - AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0); - - /* - * Stop chip and reset it. - */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP); - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET); - DvcSleepMilliSecond(100); - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_WR_IO_REG); - - /* - * Reset Adv Library error code, if any, and try - * re-initializing the chip. - */ - asc_dvc->err_code = 0; - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - status = AdvInitAsc38C1600Driver(asc_dvc); - } - else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) - { - status = AdvInitAsc38C0800Driver(asc_dvc); - } else - { - status = AdvInitAsc3550Driver(asc_dvc); - } + int status; + ushort wdtr_able, sdtr_able, tagqng_able; + ushort ppr_able = 0; + uchar tid, max_cmd[ADV_MAX_TID + 1]; + AdvPortAddr iop_base; + ushort bios_sig; + + iop_base = asc_dvc->iop_base; + + /* + * Save current per TID negotiated values. + */ + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + } + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - /* Translate initialization return value to status value. */ - if (status == 0) - { - status = ADV_TRUE; - } else - { - status = ADV_FALSE; - } + /* + * Force the AdvInitAsc3550/38C0800Driver() function to + * perform a SCSI Bus Reset by clearing the BIOS signature word. + * The initialization functions assumes a SCSI Bus Reset is not + * needed if the BIOS signature word is present. + */ + AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0); + + /* + * Stop chip and reset it. + */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP); + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET); + DvcSleepMilliSecond(100); + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, + ADV_CTRL_REG_CMD_WR_IO_REG); + + /* + * Reset Adv Library error code, if any, and try + * re-initializing the chip. + */ + asc_dvc->err_code = 0; + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + status = AdvInitAsc38C1600Driver(asc_dvc); + } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + status = AdvInitAsc38C0800Driver(asc_dvc); + } else { + status = AdvInitAsc3550Driver(asc_dvc); + } - /* - * Restore the BIOS signature word. - */ - AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + /* Translate initialization return value to status value. */ + if (status == 0) { + status = ADV_TRUE; + } else { + status = ADV_FALSE; + } - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) - { - AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - } - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) - { - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } + /* + * Restore the BIOS signature word. + */ + AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + } + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } - return status; + return status; } /* @@ -17734,158 +17386,151 @@ AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) * ADV_TRUE(1) - interrupt was pending * ADV_FALSE(0) - no interrupt was pending */ -STATIC int -AdvISR(ADV_DVC_VAR *asc_dvc) +static int AdvISR(ADV_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - uchar int_stat; - ushort target_bit; - ADV_CARR_T *free_carrp; - ADV_VADDR irq_next_vpa; - int flags; - ADV_SCSI_REQ_Q *scsiq; - - flags = DvcEnterCritical(); - - iop_base = asc_dvc->iop_base; - - /* Reading the register clears the interrupt. */ - int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); - - if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB | - ADV_INTR_STATUS_INTRC)) == 0) - { - DvcLeaveCritical(flags); - return ADV_FALSE; - } + AdvPortAddr iop_base; + uchar int_stat; + ushort target_bit; + ADV_CARR_T *free_carrp; + ADV_VADDR irq_next_vpa; + int flags; + ADV_SCSI_REQ_Q *scsiq; - /* - * Notify the driver of an asynchronous microcode condition by - * calling the ADV_DVC_VAR.async_callback function. The function - * is passed the microcode ASC_MC_INTRB_CODE byte value. - */ - if (int_stat & ADV_INTR_STATUS_INTRB) - { - uchar intrb_code; - - AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); - - if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || - asc_dvc->chip_type == ADV_CHIP_ASC38C0800) - { - if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE && - asc_dvc->carr_pending_cnt != 0) - { - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); - if (asc_dvc->chip_type == ADV_CHIP_ASC3550) - { - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); - } - } - } - - if (asc_dvc->async_callback != 0) - { - (*asc_dvc->async_callback)(asc_dvc, intrb_code); - } - } + flags = DvcEnterCritical(); - /* - * Check if the IRQ stopper carrier contains a completed request. - */ - while (((irq_next_vpa = - le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) - { - /* - * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure. - * The RISC will have set 'areq_vpa' to a virtual address. - * - * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr - * field to the carrier ADV_CARR_T.areq_vpa field. The conversion - * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr' - * in AdvExeScsiQueue(). - */ - scsiq = (ADV_SCSI_REQ_Q *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa)); - - /* - * Request finished with good status and the queue was not - * DMAed to host memory by the firmware. Set all status fields - * to indicate good status. - */ - if ((irq_next_vpa & ASC_RQ_GOOD) != 0) - { - scsiq->done_status = QD_NO_ERROR; - scsiq->host_status = scsiq->scsi_status = 0; - scsiq->data_cnt = 0L; - } - - /* - * Advance the stopper pointer to the next carrier - * ignoring the lower four bits. Free the previous - * stopper carrier. - */ - free_carrp = asc_dvc->irq_sp; - asc_dvc->irq_sp = (ADV_CARR_T *) - ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa)); - - free_carrp->next_vpa = - cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = free_carrp; - asc_dvc->carr_pending_cnt--; - - ASC_ASSERT(scsiq != NULL); - target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); - - /* - * Clear request microcode control flag. - */ - scsiq->cntl = 0; - - /* - * If the command that completed was a SCSI INQUIRY and - * LUN 0 was sent the command, then process the INQUIRY - * command information for the device. - * - * Note: If data returned were either VPD or CmdDt data, - * don't process the INQUIRY command information for - * the device, otherwise may erroneously set *_able bits. - */ - if (scsiq->done_status == QD_NO_ERROR && - scsiq->cdb[0] == INQUIRY && - scsiq->target_lun == 0 && - (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT) - == ADV_INQ_RTN_STD_INQUIRY_DATA) - { - AdvInquiryHandling(asc_dvc, scsiq); - } - - /* - * Notify the driver of the completed request by passing - * the ADV_SCSI_REQ_Q pointer to its callback function. - */ - scsiq->a_flag |= ADV_SCSIQ_DONE; - (*asc_dvc->isr_callback)(asc_dvc, scsiq); - /* - * Note: After the driver callback function is called, 'scsiq' - * can no longer be referenced. - * - * Fall through and continue processing other completed - * requests... - */ - - /* - * Disable interrupts again in case the driver inadvertently - * enabled interrupts in its callback function. - * - * The DvcEnterCritical() return value is ignored, because - * the 'flags' saved when AdvISR() was first entered will be - * used to restore the interrupt flag on exit. - */ - (void) DvcEnterCritical(); - } - DvcLeaveCritical(flags); - return ADV_TRUE; + iop_base = asc_dvc->iop_base; + + /* Reading the register clears the interrupt. */ + int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); + + if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB | + ADV_INTR_STATUS_INTRC)) == 0) { + DvcLeaveCritical(flags); + return ADV_FALSE; + } + + /* + * Notify the driver of an asynchronous microcode condition by + * calling the ADV_DVC_VAR.async_callback function. The function + * is passed the microcode ASC_MC_INTRB_CODE byte value. + */ + if (int_stat & ADV_INTR_STATUS_INTRB) { + uchar intrb_code; + + AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); + + if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || + asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE && + asc_dvc->carr_pending_cnt != 0) { + AdvWriteByteRegister(iop_base, IOPB_TICKLE, + ADV_TICKLE_A); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { + AdvWriteByteRegister(iop_base, + IOPB_TICKLE, + ADV_TICKLE_NOP); + } + } + } + + if (asc_dvc->async_callback != 0) { + (*asc_dvc->async_callback) (asc_dvc, intrb_code); + } + } + + /* + * Check if the IRQ stopper carrier contains a completed request. + */ + while (((irq_next_vpa = + le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) { + /* + * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure. + * The RISC will have set 'areq_vpa' to a virtual address. + * + * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr + * field to the carrier ADV_CARR_T.areq_vpa field. The conversion + * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr' + * in AdvExeScsiQueue(). + */ + scsiq = (ADV_SCSI_REQ_Q *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa)); + + /* + * Request finished with good status and the queue was not + * DMAed to host memory by the firmware. Set all status fields + * to indicate good status. + */ + if ((irq_next_vpa & ASC_RQ_GOOD) != 0) { + scsiq->done_status = QD_NO_ERROR; + scsiq->host_status = scsiq->scsi_status = 0; + scsiq->data_cnt = 0L; + } + + /* + * Advance the stopper pointer to the next carrier + * ignoring the lower four bits. Free the previous + * stopper carrier. + */ + free_carrp = asc_dvc->irq_sp; + asc_dvc->irq_sp = (ADV_CARR_T *) + ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa)); + + free_carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = free_carrp; + asc_dvc->carr_pending_cnt--; + + ASC_ASSERT(scsiq != NULL); + target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); + + /* + * Clear request microcode control flag. + */ + scsiq->cntl = 0; + + /* + * If the command that completed was a SCSI INQUIRY and + * LUN 0 was sent the command, then process the INQUIRY + * command information for the device. + * + * Note: If data returned were either VPD or CmdDt data, + * don't process the INQUIRY command information for + * the device, otherwise may erroneously set *_able bits. + */ + if (scsiq->done_status == QD_NO_ERROR && + scsiq->cdb[0] == INQUIRY && + scsiq->target_lun == 0 && + (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT) + == ADV_INQ_RTN_STD_INQUIRY_DATA) { + AdvInquiryHandling(asc_dvc, scsiq); + } + + /* + * Notify the driver of the completed request by passing + * the ADV_SCSI_REQ_Q pointer to its callback function. + */ + scsiq->a_flag |= ADV_SCSIQ_DONE; + (*asc_dvc->isr_callback) (asc_dvc, scsiq); + /* + * Note: After the driver callback function is called, 'scsiq' + * can no longer be referenced. + * + * Fall through and continue processing other completed + * requests... + */ + + /* + * Disable interrupts again in case the driver inadvertently + * enabled interrupts in its callback function. + * + * The DvcEnterCritical() return value is ignored, because + * the 'flags' saved when AdvISR() was first entered will be + * used to restore the interrupt flag on exit. + */ + (void)DvcEnterCritical(); + } + DvcLeaveCritical(flags); + return ADV_TRUE; } /* @@ -17902,71 +17547,67 @@ AdvISR(ADV_DVC_VAR *asc_dvc) * ADV_FALSE - command failed * ADV_ERROR - command timed out */ -STATIC int +static int AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, - ushort idle_cmd, - ADV_DCNT idle_cmd_parameter) + ushort idle_cmd, ADV_DCNT idle_cmd_parameter) { - ulong last_int_level; - int result; - ADV_DCNT i, j; - AdvPortAddr iop_base; - - last_int_level = DvcEnterCritical(); - - iop_base = asc_dvc->iop_base; - - /* - * Clear the idle command status which is set by the microcode - * to a non-zero value to indicate when the command is completed. - * The non-zero result is one of the IDLE_CMD_STATUS_* values - * defined in a_advlib.h. - */ - AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort) 0); - - /* - * Write the idle command value after the idle command parameter - * has been written to avoid a race condition. If the order is not - * followed, the microcode may process the idle command before the - * parameters have been written to LRAM. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER, - cpu_to_le32(idle_cmd_parameter)); - AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); - - /* - * Tickle the RISC to tell it to process the idle command. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B); - if (asc_dvc->chip_type == ADV_CHIP_ASC3550) - { - /* - * Clear the tickle value. In the ASC-3550 the RISC flag - * command 'clr_tickle_b' does not work unless the host - * value is cleared. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); - } + ulong last_int_level; + int result; + ADV_DCNT i, j; + AdvPortAddr iop_base; + + last_int_level = DvcEnterCritical(); + + iop_base = asc_dvc->iop_base; + + /* + * Clear the idle command status which is set by the microcode + * to a non-zero value to indicate when the command is completed. + * The non-zero result is one of the IDLE_CMD_STATUS_* values + * defined in a_advlib.h. + */ + AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0); + + /* + * Write the idle command value after the idle command parameter + * has been written to avoid a race condition. If the order is not + * followed, the microcode may process the idle command before the + * parameters have been written to LRAM. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER, + cpu_to_le32(idle_cmd_parameter)); + AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); + + /* + * Tickle the RISC to tell it to process the idle command. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { + /* + * Clear the tickle value. In the ASC-3550 the RISC flag + * command 'clr_tickle_b' does not work unless the host + * value is cleared. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); + } - /* Wait for up to 100 millisecond for the idle command to timeout. */ - for (i = 0; i < SCSI_WAIT_100_MSEC; i++) - { - /* Poll once each microsecond for command completion. */ - for (j = 0; j < SCSI_US_PER_MSEC; j++) - { - AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, result); - if (result != 0) - { - DvcLeaveCritical(last_int_level); - return result; - } - DvcDelayMicroSecond(asc_dvc, (ushort) 1); - } - } + /* Wait for up to 100 millisecond for the idle command to timeout. */ + for (i = 0; i < SCSI_WAIT_100_MSEC; i++) { + /* Poll once each microsecond for command completion. */ + for (j = 0; j < SCSI_US_PER_MSEC; j++) { + AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, + result); + if (result != 0) { + DvcLeaveCritical(last_int_level); + return result; + } + DvcDelayMicroSecond(asc_dvc, (ushort)1); + } + } - ASC_ASSERT(0); /* The idle command should never timeout. */ - DvcLeaveCritical(last_int_level); - return ADV_ERROR; + ASC_ASSERT(0); /* The idle command should never timeout. */ + DvcLeaveCritical(last_int_level); + return ADV_ERROR; } /* @@ -17976,179 +17617,1415 @@ AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, * microcode operating variables that affect WDTR, SDTR, and Tag * Queuing. */ -STATIC void -AdvInquiryHandling( - ADV_DVC_VAR *asc_dvc, - ADV_SCSI_REQ_Q *scsiq) +static void AdvInquiryHandling(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) { - AdvPortAddr iop_base; - uchar tid; - ADV_SCSI_INQUIRY *inq; - ushort tidmask; - ushort cfg_word; + AdvPortAddr iop_base; + uchar tid; + ADV_SCSI_INQUIRY *inq; + ushort tidmask; + ushort cfg_word; + + /* + * AdvInquiryHandling() requires up to INQUIRY information Byte 7 + * to be available. + * + * If less than 8 bytes of INQUIRY information were requested or less + * than 8 bytes were transferred, then return. cdb[4] is the request + * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the + * microcode to the transfer residual count. + */ + + if (scsiq->cdb[4] < 8 || + (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) < 8) { + return; + } - /* - * AdvInquiryHandling() requires up to INQUIRY information Byte 7 - * to be available. - * - * If less than 8 bytes of INQUIRY information were requested or less - * than 8 bytes were transferred, then return. cdb[4] is the request - * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the - * microcode to the transfer residual count. - */ - - if (scsiq->cdb[4] < 8 || - (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) < 8) - { - return; - } + iop_base = asc_dvc->iop_base; + tid = scsiq->target_id; - iop_base = asc_dvc->iop_base; - tid = scsiq->target_id; + inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr; - inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr; + /* + * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices. + */ + if (ADV_INQ_RESPONSE_FMT(inq) < 2 && ADV_INQ_ANSI_VER(inq) < 2) { + return; + } else { + /* + * INQUIRY Byte 7 Handling + * + * Use a device's INQUIRY byte 7 to determine whether it + * supports WDTR, SDTR, and Tag Queuing. If the feature + * is enabled in the EEPROM and the device supports the + * feature, then enable it in the microcode. + */ - /* - * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices. - */ - if (ADV_INQ_RESPONSE_FMT(inq) < 2 && ADV_INQ_ANSI_VER(inq) < 2) - { - return; - } else - { - /* - * INQUIRY Byte 7 Handling - * - * Use a device's INQUIRY byte 7 to determine whether it - * supports WDTR, SDTR, and Tag Queuing. If the feature - * is enabled in the EEPROM and the device supports the - * feature, then enable it in the microcode. - */ - - tidmask = ADV_TID_TO_TIDMASK(tid); - - /* - * Wide Transfers - * - * If the EEPROM enabled WDTR for the device and the device - * supports wide bus (16 bit) transfers, then turn on the - * device's 'wdtr_able' bit and write the new value to the - * microcode. - */ - if ((asc_dvc->wdtr_able & tidmask) && ADV_INQ_WIDE16(inq)) - { - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); - if ((cfg_word & tidmask) == 0) - { - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); - - /* - * Clear the microcode "SDTR negotiation" and "WDTR - * negotiation" done indicators for the target to cause - * it to negotiate with the new setting set above. - * WDTR when accepted causes the target to enter - * asynchronous mode, so SDTR must be negotiated. - */ - AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); - cfg_word &= ~tidmask; - AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); - AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); - cfg_word &= ~tidmask; - AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); - } - } - - /* - * Synchronous Transfers - * - * If the EEPROM enabled SDTR for the device and the device - * supports synchronous transfers, then turn on the device's - * 'sdtr_able' bit. Write the new value to the microcode. - */ - if ((asc_dvc->sdtr_able & tidmask) && ADV_INQ_SYNC(inq)) - { - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); - if ((cfg_word & tidmask) == 0) - { - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); - - /* - * Clear the microcode "SDTR negotiation" done indicator - * for the target to cause it to negotiate with the new - * setting set above. - */ - AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); - cfg_word &= ~tidmask; - AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); - } - } - /* - * If the Inquiry data included enough space for the SPI-3 - * Clocking field, then check if DT mode is supported. - */ - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600 && - (scsiq->cdb[4] >= 57 || - (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) >= 57)) - { - /* - * PPR (Parallel Protocol Request) Capable - * - * If the device supports DT mode, then it must be PPR capable. - * The PPR message will be used in place of the SDTR and WDTR - * messages to negotiate synchronous speed and offset, transfer - * width, and protocol options. - */ - if (ADV_INQ_CLOCKING(inq) & ADV_INQ_CLOCKING_DT_ONLY) - { - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, asc_dvc->ppr_able); - asc_dvc->ppr_able |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, asc_dvc->ppr_able); - } - } - - /* - * If the EEPROM enabled Tag Queuing for the device and the - * device supports Tag Queueing, then turn on the device's - * 'tagqng_enable' bit in the microcode and set the microcode - * maximum command count to the ADV_DVC_VAR 'max_dvc_qng' - * value. - * - * Tag Queuing is disabled for the BIOS which runs in polled - * mode and would see no benefit from Tag Queuing. Also by - * disabling Tag Queuing in the BIOS devices with Tag Queuing - * bugs will at least work with the BIOS. - */ - if ((asc_dvc->tagqng_able & tidmask) && ADV_INQ_CMD_QUEUE(inq)) - { - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); - - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - asc_dvc->max_dvc_qng); - } - } + tidmask = ADV_TID_TO_TIDMASK(tid); + + /* + * Wide Transfers + * + * If the EEPROM enabled WDTR for the device and the device + * supports wide bus (16 bit) transfers, then turn on the + * device's 'wdtr_able' bit and write the new value to the + * microcode. + */ + if ((asc_dvc->wdtr_able & tidmask) && ADV_INQ_WIDE16(inq)) { + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); + if ((cfg_word & tidmask) == 0) { + cfg_word |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + cfg_word); + + /* + * Clear the microcode "SDTR negotiation" and "WDTR + * negotiation" done indicators for the target to cause + * it to negotiate with the new setting set above. + * WDTR when accepted causes the target to enter + * asynchronous mode, so SDTR must be negotiated. + */ + AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, + cfg_word); + cfg_word &= ~tidmask; + AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, + cfg_word); + AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, + cfg_word); + cfg_word &= ~tidmask; + AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, + cfg_word); + } + } + + /* + * Synchronous Transfers + * + * If the EEPROM enabled SDTR for the device and the device + * supports synchronous transfers, then turn on the device's + * 'sdtr_able' bit. Write the new value to the microcode. + */ + if ((asc_dvc->sdtr_able & tidmask) && ADV_INQ_SYNC(inq)) { + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); + if ((cfg_word & tidmask) == 0) { + cfg_word |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + cfg_word); + + /* + * Clear the microcode "SDTR negotiation" done indicator + * for the target to cause it to negotiate with the new + * setting set above. + */ + AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, + cfg_word); + cfg_word &= ~tidmask; + AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, + cfg_word); + } + } + /* + * If the Inquiry data included enough space for the SPI-3 + * Clocking field, then check if DT mode is supported. + */ + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600 && + (scsiq->cdb[4] >= 57 || + (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) >= 57)) { + /* + * PPR (Parallel Protocol Request) Capable + * + * If the device supports DT mode, then it must be PPR capable. + * The PPR message will be used in place of the SDTR and WDTR + * messages to negotiate synchronous speed and offset, transfer + * width, and protocol options. + */ + if (ADV_INQ_CLOCKING(inq) & ADV_INQ_CLOCKING_DT_ONLY) { + AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, + asc_dvc->ppr_able); + asc_dvc->ppr_able |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, + asc_dvc->ppr_able); + } + } + + /* + * If the EEPROM enabled Tag Queuing for the device and the + * device supports Tag Queueing, then turn on the device's + * 'tagqng_enable' bit in the microcode and set the microcode + * maximum command count to the ADV_DVC_VAR 'max_dvc_qng' + * value. + * + * Tag Queuing is disabled for the BIOS which runs in polled + * mode and would see no benefit from Tag Queuing. Also by + * disabling Tag Queuing in the BIOS devices with Tag Queuing + * bugs will at least work with the BIOS. + */ + if ((asc_dvc->tagqng_able & tidmask) && ADV_INQ_CMD_QUEUE(inq)) { + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); + cfg_word |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + cfg_word); + + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + asc_dvc->max_dvc_qng); + } + } } + MODULE_LICENSE("Dual BSD/GPL"); +static struct Scsi_Host *__devinit +advansys_board_found(int iop, struct device *dev, int bus_type) +{ + struct Scsi_Host *shost; + struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL; + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp = NULL; + ADV_DVC_VAR *adv_dvc_varp = NULL; + adv_sgblk_t *sgp = NULL; + int share_irq = FALSE; + int iolen = 0; + ADV_PADDR pci_memory_address; + int warn_code, err_code; + int ret; + + /* + * Adapter found. + * + * Register the adapter, get its configuration, and + * initialize it. + */ + ASC_DBG(2, "advansys_board_found: scsi_register()\n"); + shost = scsi_register(&driver_template, sizeof(asc_board_t)); + + if (!shost) + return NULL; + + /* Save a pointer to the Scsi_Host of each board found. */ + asc_host[asc_board_count++] = shost; + + /* Initialize private per board data */ + boardp = ASC_BOARDP(shost); + memset(boardp, 0, sizeof(asc_board_t)); + boardp->id = asc_board_count - 1; + + /* Initialize spinlock. */ + spin_lock_init(&boardp->lock); + + /* + * Handle both narrow and wide boards. + * + * If a Wide board was detected, set the board structure + * wide board flag. Set-up the board structure based on + * the board type. + */ +#ifdef CONFIG_PCI + if (bus_type == ASC_IS_PCI && + (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW || + pdev->device == PCI_DEVICE_ID_38C0800_REV1 || + pdev->device == PCI_DEVICE_ID_38C1600_REV1)) { + boardp->flags |= ASC_IS_WIDE_BOARD; + } +#endif /* CONFIG_PCI */ + + if (ASC_NARROW_BOARD(boardp)) { + ASC_DBG(1, "advansys_board_found: narrow board\n"); + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + asc_dvc_varp->bus_type = bus_type; + asc_dvc_varp->drv_ptr = boardp; + asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg; + asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0]; + asc_dvc_varp->iop_base = iop; + asc_dvc_varp->isr_callback = asc_isr_callback; + } else { + ASC_DBG(1, "advansys_board_found: wide board\n"); + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; + adv_dvc_varp->drv_ptr = boardp; + adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg; + adv_dvc_varp->isr_callback = adv_isr_callback; + adv_dvc_varp->async_callback = adv_async_callback; +#ifdef CONFIG_PCI + if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) { + ASC_DBG(1, "advansys_board_found: ASC-3550\n"); + adv_dvc_varp->chip_type = ADV_CHIP_ASC3550; + } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) { + ASC_DBG(1, "advansys_board_found: ASC-38C0800\n"); + adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800; + } else { + ASC_DBG(1, "advansys_board_found: ASC-38C1600\n"); + adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600; + } +#endif /* CONFIG_PCI */ + + /* + * Map the board's registers into virtual memory for + * PCI slave access. Only memory accesses are used to + * access the board's registers. + * + * Note: The PCI register base address is not always + * page aligned, but the address passed to ioremap() + * must be page aligned. It is guaranteed that the + * PCI register base address will not cross a page + * boundary. + */ + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + iolen = ADV_3550_IOLEN; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + iolen = ADV_38C0800_IOLEN; + } else { + iolen = ADV_38C1600_IOLEN; + } +#ifdef CONFIG_PCI + pci_memory_address = pci_resource_start(pdev, 1); + ASC_DBG1(1, + "advansys_board_found: pci_memory_address: 0x%lx\n", + (ulong)pci_memory_address); + if ((boardp->ioremap_addr = + ioremap(pci_memory_address & PAGE_MASK, PAGE_SIZE)) == 0) { + ASC_PRINT3 + ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n", + boardp->id, pci_memory_address, iolen); + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + ASC_DBG1(1, + "advansys_board_found: ioremap_addr: 0x%lx\n", + (ulong)boardp->ioremap_addr); + adv_dvc_varp->iop_base = (AdvPortAddr) + (boardp->ioremap_addr + + (pci_memory_address - (pci_memory_address & PAGE_MASK))); + ASC_DBG1(1, + "advansys_board_found: iop_base: 0x%lx\n", + adv_dvc_varp->iop_base); +#endif /* CONFIG_PCI */ + + /* + * Even though it isn't used to access wide boards, other + * than for the debug line below, save I/O Port address so + * that it can be reported. + */ + boardp->ioport = iop; + + ASC_DBG2(1, + "advansys_board_found: iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n", + (ushort)inp(iop + 1), (ushort)inpw(iop)); + } + +#ifdef CONFIG_PROC_FS + /* + * Allocate buffer for printing information from + * /proc/scsi/advansys/[0...]. + */ + if ((boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) { + ASC_PRINT3 + ("advansys_board_found: board %d: kmalloc(%d, %d) returned NULL\n", + boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC); + scsi_unregister(shost); + asc_board_count--; + return NULL; + } +#endif /* CONFIG_PROC_FS */ + + if (ASC_NARROW_BOARD(boardp)) { + asc_dvc_varp->cfg->dev = dev; + /* + * Set the board bus type and PCI IRQ before + * calling AscInitGetConfig(). + */ + switch (asc_dvc_varp->bus_type) { +#ifdef CONFIG_ISA + case ASC_IS_ISA: + shost->unchecked_isa_dma = TRUE; + share_irq = FALSE; + break; + case ASC_IS_VL: + shost->unchecked_isa_dma = FALSE; + share_irq = FALSE; + break; + case ASC_IS_EISA: + shost->unchecked_isa_dma = FALSE; + share_irq = TRUE; + break; +#endif /* CONFIG_ISA */ +#ifdef CONFIG_PCI + case ASC_IS_PCI: + shost->irq = asc_dvc_varp->irq_no = pdev->irq; + asc_dvc_varp->cfg->pci_slot_info = + ASC_PCI_MKID(pdev->bus->number, + PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn)); + shost->unchecked_isa_dma = FALSE; + share_irq = TRUE; + break; +#endif /* CONFIG_PCI */ + default: + ASC_PRINT2 + ("advansys_board_found: board %d: unknown adapter type: %d\n", + boardp->id, asc_dvc_varp->bus_type); + shost->unchecked_isa_dma = TRUE; + share_irq = FALSE; + break; + } + } else { + adv_dvc_varp->cfg->dev = dev; + /* + * For Wide boards set PCI information before calling + * AdvInitGetConfig(). + */ +#ifdef CONFIG_PCI + shost->irq = adv_dvc_varp->irq_no = pdev->irq; + adv_dvc_varp->cfg->pci_slot_info = + ASC_PCI_MKID(pdev->bus->number, + PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn)); + shost->unchecked_isa_dma = FALSE; + share_irq = TRUE; +#endif /* CONFIG_PCI */ + } + + /* + * Read the board configuration. + */ + if (ASC_NARROW_BOARD(boardp)) { + /* + * NOTE: AscInitGetConfig() may change the board's + * bus_type value. The bus_type value should no + * longer be used. If the bus_type field must be + * referenced only use the bit-wise AND operator "&". + */ + ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n"); + switch (ret = AscInitGetConfig(asc_dvc_varp)) { + case 0: /* No error */ + break; + case ASC_WARN_IO_PORT_ROTATE: + ASC_PRINT1 + ("AscInitGetConfig: board %d: I/O port address modified\n", + boardp->id); + break; + case ASC_WARN_AUTO_CONFIG: + ASC_PRINT1 + ("AscInitGetConfig: board %d: I/O port increment switch enabled\n", + boardp->id); + break; + case ASC_WARN_EEPROM_CHKSUM: + ASC_PRINT1 + ("AscInitGetConfig: board %d: EEPROM checksum error\n", + boardp->id); + break; + case ASC_WARN_IRQ_MODIFIED: + ASC_PRINT1 + ("AscInitGetConfig: board %d: IRQ modified\n", + boardp->id); + break; + case ASC_WARN_CMD_QNG_CONFLICT: + ASC_PRINT1 + ("AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n", + boardp->id); + break; + default: + ASC_PRINT2 + ("AscInitGetConfig: board %d: unknown warning: 0x%x\n", + boardp->id, ret); + break; + } + if ((err_code = asc_dvc_varp->err_code) != 0) { + ASC_PRINT3 + ("AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", + boardp->id, + asc_dvc_varp->init_state, asc_dvc_varp->err_code); + } + } else { + ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n"); + if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) { + ASC_PRINT2 + ("AdvInitGetConfig: board %d: warning: 0x%x\n", + boardp->id, ret); + } + if ((err_code = adv_dvc_varp->err_code) != 0) { + ASC_PRINT2 + ("AdvInitGetConfig: board %d error: err_code 0x%x\n", + boardp->id, adv_dvc_varp->err_code); + } + } + + if (err_code != 0) { +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + + /* + * Save the EEPROM configuration so that it can be displayed + * from /proc/scsi/advansys/[0...]. + */ + if (ASC_NARROW_BOARD(boardp)) { + + ASCEEP_CONFIG *ep; + + /* + * Set the adapter's target id bit in the 'init_tidmask' field. + */ + boardp->init_tidmask |= + ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id); + + /* + * Save EEPROM settings for the board. + */ + ep = &boardp->eep_config.asc_eep; + + ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable; + ep->disc_enable = asc_dvc_varp->cfg->disc_enable; + ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled; + ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed); + ep->start_motor = asc_dvc_varp->start_motor; + ep->cntl = asc_dvc_varp->dvc_cntl; + ep->no_scam = asc_dvc_varp->no_scam; + ep->max_total_qng = asc_dvc_varp->max_total_qng; + ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id); + /* 'max_tag_qng' is set to the same value for every device. */ + ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0]; + ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0]; + ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1]; + ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2]; + ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3]; + ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4]; + ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5]; + + /* + * Modify board configuration. + */ + ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n"); + switch (ret = AscInitSetConfig(asc_dvc_varp)) { + case 0: /* No error. */ + break; + case ASC_WARN_IO_PORT_ROTATE: + ASC_PRINT1 + ("AscInitSetConfig: board %d: I/O port address modified\n", + boardp->id); + break; + case ASC_WARN_AUTO_CONFIG: + ASC_PRINT1 + ("AscInitSetConfig: board %d: I/O port increment switch enabled\n", + boardp->id); + break; + case ASC_WARN_EEPROM_CHKSUM: + ASC_PRINT1 + ("AscInitSetConfig: board %d: EEPROM checksum error\n", + boardp->id); + break; + case ASC_WARN_IRQ_MODIFIED: + ASC_PRINT1 + ("AscInitSetConfig: board %d: IRQ modified\n", + boardp->id); + break; + case ASC_WARN_CMD_QNG_CONFLICT: + ASC_PRINT1 + ("AscInitSetConfig: board %d: tag queuing w/o disconnects\n", + boardp->id); + break; + default: + ASC_PRINT2 + ("AscInitSetConfig: board %d: unknown warning: 0x%x\n", + boardp->id, ret); + break; + } + if (asc_dvc_varp->err_code != 0) { + ASC_PRINT3 + ("AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", + boardp->id, + asc_dvc_varp->init_state, asc_dvc_varp->err_code); +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + + /* + * Finish initializing the 'Scsi_Host' structure. + */ + /* AscInitSetConfig() will set the IRQ for non-PCI boards. */ + if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) { + shost->irq = asc_dvc_varp->irq_no; + } + } else { + ADVEEP_3550_CONFIG *ep_3550; + ADVEEP_38C0800_CONFIG *ep_38C0800; + ADVEEP_38C1600_CONFIG *ep_38C1600; + + /* + * Save Wide EEP Configuration Information. + */ + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + ep_3550 = &boardp->eep_config.adv_3550_eep; + + ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id; + ep_3550->max_host_qng = adv_dvc_varp->max_host_qng; + ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng; + ep_3550->termination = adv_dvc_varp->cfg->termination; + ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable; + ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl; + ep_3550->wdtr_able = adv_dvc_varp->wdtr_able; + ep_3550->sdtr_able = adv_dvc_varp->sdtr_able; + ep_3550->ultra_able = adv_dvc_varp->ultra_able; + ep_3550->tagqng_able = adv_dvc_varp->tagqng_able; + ep_3550->start_motor = adv_dvc_varp->start_motor; + ep_3550->scsi_reset_delay = + adv_dvc_varp->scsi_reset_wait; + ep_3550->serial_number_word1 = + adv_dvc_varp->cfg->serial1; + ep_3550->serial_number_word2 = + adv_dvc_varp->cfg->serial2; + ep_3550->serial_number_word3 = + adv_dvc_varp->cfg->serial3; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; + + ep_38C0800->adapter_scsi_id = + adv_dvc_varp->chip_scsi_id; + ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng; + ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng; + ep_38C0800->termination_lvd = + adv_dvc_varp->cfg->termination; + ep_38C0800->disc_enable = + adv_dvc_varp->cfg->disc_enable; + ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl; + ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able; + ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able; + ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1; + ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2; + ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3; + ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4; + ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able; + ep_38C0800->start_motor = adv_dvc_varp->start_motor; + ep_38C0800->scsi_reset_delay = + adv_dvc_varp->scsi_reset_wait; + ep_38C0800->serial_number_word1 = + adv_dvc_varp->cfg->serial1; + ep_38C0800->serial_number_word2 = + adv_dvc_varp->cfg->serial2; + ep_38C0800->serial_number_word3 = + adv_dvc_varp->cfg->serial3; + } else { + ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; + + ep_38C1600->adapter_scsi_id = + adv_dvc_varp->chip_scsi_id; + ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng; + ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng; + ep_38C1600->termination_lvd = + adv_dvc_varp->cfg->termination; + ep_38C1600->disc_enable = + adv_dvc_varp->cfg->disc_enable; + ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl; + ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able; + ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able; + ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1; + ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2; + ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3; + ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4; + ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able; + ep_38C1600->start_motor = adv_dvc_varp->start_motor; + ep_38C1600->scsi_reset_delay = + adv_dvc_varp->scsi_reset_wait; + ep_38C1600->serial_number_word1 = + adv_dvc_varp->cfg->serial1; + ep_38C1600->serial_number_word2 = + adv_dvc_varp->cfg->serial2; + ep_38C1600->serial_number_word3 = + adv_dvc_varp->cfg->serial3; + } + + /* + * Set the adapter's target id bit in the 'init_tidmask' field. + */ + boardp->init_tidmask |= + ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id); + + /* + * Finish initializing the 'Scsi_Host' structure. + */ + shost->irq = adv_dvc_varp->irq_no; + } + + /* + * Channels are numbered beginning with 0. For AdvanSys one host + * structure supports one channel. Multi-channel boards have a + * separate host structure for each channel. + */ + shost->max_channel = 0; + if (ASC_NARROW_BOARD(boardp)) { + shost->max_id = ASC_MAX_TID + 1; + shost->max_lun = ASC_MAX_LUN + 1; + + shost->io_port = asc_dvc_varp->iop_base; + boardp->asc_n_io_port = ASC_IOADR_GAP; + shost->this_id = asc_dvc_varp->cfg->chip_scsi_id; + + /* Set maximum number of queues the adapter can handle. */ + shost->can_queue = asc_dvc_varp->max_total_qng; + } else { + shost->max_id = ADV_MAX_TID + 1; + shost->max_lun = ADV_MAX_LUN + 1; + + /* + * Save the I/O Port address and length even though + * I/O ports are not used to access Wide boards. + * Instead the Wide boards are accessed with + * PCI Memory Mapped I/O. + */ + shost->io_port = iop; + boardp->asc_n_io_port = iolen; + + shost->this_id = adv_dvc_varp->chip_scsi_id; + + /* Set maximum number of queues the adapter can handle. */ + shost->can_queue = adv_dvc_varp->max_host_qng; + } + + /* + * 'n_io_port' currently is one byte. + * + * Set a value to 'n_io_port', but never referenced it because + * it may be truncated. + */ + shost->n_io_port = boardp->asc_n_io_port <= 255 ? + boardp->asc_n_io_port : 255; + + /* + * Following v1.3.89, 'cmd_per_lun' is no longer needed + * and should be set to zero. + * + * But because of a bug introduced in v1.3.89 if the driver is + * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level + * SCSI function 'allocate_device' will panic. To allow the driver + * to work as a module in these kernels set 'cmd_per_lun' to 1. + * + * Note: This is wrong. cmd_per_lun should be set to the depth + * you want on untagged devices always. + #ifdef MODULE + */ + shost->cmd_per_lun = 1; +/* #else + shost->cmd_per_lun = 0; +#endif */ + + /* + * Set the maximum number of scatter-gather elements the + * adapter can handle. + */ + if (ASC_NARROW_BOARD(boardp)) { + /* + * Allow two commands with 'sg_tablesize' scatter-gather + * elements to be executed simultaneously. This value is + * the theoretical hardware limit. It may be decreased + * below. + */ + shost->sg_tablesize = + (((asc_dvc_varp->max_total_qng - 2) / 2) * + ASC_SG_LIST_PER_Q) + 1; + } else { + shost->sg_tablesize = ADV_MAX_SG_LIST; + } + + /* + * The value of 'sg_tablesize' can not exceed the SCSI + * mid-level driver definition of SG_ALL. SG_ALL also + * must not be exceeded, because it is used to define the + * size of the scatter-gather table in 'struct asc_sg_head'. + */ + if (shost->sg_tablesize > SG_ALL) { + shost->sg_tablesize = SG_ALL; + } + + ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize); + + /* BIOS start address. */ + if (ASC_NARROW_BOARD(boardp)) { + shost->base = ((ulong) + AscGetChipBiosAddress(asc_dvc_varp-> + iop_base, + asc_dvc_varp->bus_type)); + } else { + /* + * Fill-in BIOS board variables. The Wide BIOS saves + * information in LRAM that is used by the driver. + */ + AdvReadWordLram(adv_dvc_varp->iop_base, + BIOS_SIGNATURE, boardp->bios_signature); + AdvReadWordLram(adv_dvc_varp->iop_base, + BIOS_VERSION, boardp->bios_version); + AdvReadWordLram(adv_dvc_varp->iop_base, + BIOS_CODESEG, boardp->bios_codeseg); + AdvReadWordLram(adv_dvc_varp->iop_base, + BIOS_CODELEN, boardp->bios_codelen); + + ASC_DBG2(1, + "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n", + boardp->bios_signature, boardp->bios_version); + + ASC_DBG2(1, + "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n", + boardp->bios_codeseg, boardp->bios_codelen); + + /* + * If the BIOS saved a valid signature, then fill in + * the BIOS code segment base address. + */ + if (boardp->bios_signature == 0x55AA) { + /* + * Convert x86 realmode code segment to a linear + * address by shifting left 4. + */ + shost->base = ((ulong)boardp->bios_codeseg << 4); + } else { + shost->base = 0; + } + } + + /* + * Register Board Resources - I/O Port, DMA, IRQ + */ + + /* + * Register I/O port range. + * + * For Wide boards the I/O ports are not used to access + * the board, but request the region anyway. + * + * 'shost->n_io_port' is not referenced, because it may be truncated. + */ + ASC_DBG2(2, + "advansys_board_found: request_region port 0x%lx, len 0x%x\n", + (ulong)shost->io_port, boardp->asc_n_io_port); + if (request_region(shost->io_port, boardp->asc_n_io_port, + "advansys") == NULL) { + ASC_PRINT3 + ("advansys_board_found: board %d: request_region() failed, port 0x%lx, len 0x%x\n", + boardp->id, (ulong)shost->io_port, boardp->asc_n_io_port); +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + + /* Register DMA Channel for Narrow boards. */ + shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ +#ifdef CONFIG_ISA + if (ASC_NARROW_BOARD(boardp)) { + /* Register DMA channel for ISA bus. */ + if (asc_dvc_varp->bus_type & ASC_IS_ISA) { + shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel; + if ((ret = + request_dma(shost->dma_channel, "advansys")) != 0) { + ASC_PRINT3 + ("advansys_board_found: board %d: request_dma() %d failed %d\n", + boardp->id, shost->dma_channel, ret); + release_region(shost->io_port, + boardp->asc_n_io_port); +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + AscEnableIsaDma(shost->dma_channel); + } + } +#endif /* CONFIG_ISA */ + + /* Register IRQ Number. */ + ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq); + /* + * If request_irq() fails with the IRQF_DISABLED flag set, + * then try again without the IRQF_DISABLED flag set. This + * allows IRQ sharing to work even with other drivers that + * do not set the IRQF_DISABLED flag. + * + * If IRQF_DISABLED is not set, then interrupts are enabled + * before the driver interrupt function is called. + */ + if (((ret = request_irq(shost->irq, advansys_interrupt, + IRQF_DISABLED | (share_irq == + TRUE ? + IRQF_SHARED : + 0), "advansys", boardp)) != 0) + && + ((ret = + request_irq(shost->irq, advansys_interrupt, + (share_irq == TRUE ? IRQF_SHARED : 0), + "advansys", boardp)) != 0)) { + if (ret == -EBUSY) { + ASC_PRINT2 + ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n", + boardp->id, shost->irq); + } else if (ret == -EINVAL) { + ASC_PRINT2 + ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n", + boardp->id, shost->irq); + } else { + ASC_PRINT3 + ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n", + boardp->id, shost->irq, ret); + } + release_region(shost->io_port, boardp->asc_n_io_port); + iounmap(boardp->ioremap_addr); + if (shost->dma_channel != NO_ISA_DMA) { + free_dma(shost->dma_channel); + } +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + + /* + * Initialize board RISC chip and enable interrupts. + */ + if (ASC_NARROW_BOARD(boardp)) { + ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n"); + warn_code = AscInitAsc1000Driver(asc_dvc_varp); + err_code = asc_dvc_varp->err_code; + + if (warn_code || err_code) { + ASC_PRINT4 + ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n", + boardp->id, + asc_dvc_varp->init_state, warn_code, err_code); + } + } else { + ADV_CARR_T *carrp; + int req_cnt = 0; + adv_req_t *reqp = NULL; + int sg_cnt = 0; + + /* + * Allocate buffer carrier structures. The total size + * is about 4 KB, so allocate all at once. + */ + carrp = (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC); + ASC_DBG1(1, "advansys_board_found: carrp 0x%lx\n", (ulong)carrp); + + if (carrp == NULL) { + goto kmalloc_error; + } + + /* + * Allocate up to 'max_host_qng' request structures for + * the Wide board. The total size is about 16 KB, so + * allocate all at once. If the allocation fails decrement + * and try again. + */ + for (req_cnt = adv_dvc_varp->max_host_qng; + req_cnt > 0; req_cnt--) { + + reqp = (adv_req_t *) + kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC); + + ASC_DBG3(1, + "advansys_board_found: reqp 0x%lx, req_cnt %d, bytes %lu\n", + (ulong)reqp, req_cnt, + (ulong)sizeof(adv_req_t) * req_cnt); + + if (reqp != NULL) { + break; + } + } + if (reqp == NULL) { + goto kmalloc_error; + } + + /* + * Allocate up to ADV_TOT_SG_BLOCK request structures for + * the Wide board. Each structure is about 136 bytes. + */ + boardp->adv_sgblkp = NULL; + for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) { + + sgp = (adv_sgblk_t *) + kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC); + + if (sgp == NULL) { + break; + } + + sgp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgp; + + } + ASC_DBG3(1, + "advansys_board_found: sg_cnt %d * %u = %u bytes\n", + sg_cnt, sizeof(adv_sgblk_t), + (unsigned)(sizeof(adv_sgblk_t) * sg_cnt)); + + /* + * If no request structures or scatter-gather structures could + * be allocated, then return an error. Otherwise continue with + * initialization. + */ + kmalloc_error: + if (carrp == NULL) { + ASC_PRINT1 + ("advansys_board_found: board %d error: failed to kmalloc() carrier buffer.\n", + boardp->id); + err_code = ADV_ERROR; + } else if (reqp == NULL) { + kfree(carrp); + ASC_PRINT1 + ("advansys_board_found: board %d error: failed to kmalloc() adv_req_t buffer.\n", + boardp->id); + err_code = ADV_ERROR; + } else if (boardp->adv_sgblkp == NULL) { + kfree(carrp); + kfree(reqp); + ASC_PRINT1 + ("advansys_board_found: board %d error: failed to kmalloc() adv_sgblk_t buffers.\n", + boardp->id); + err_code = ADV_ERROR; + } else { + + /* Save carrier buffer pointer. */ + boardp->orig_carrp = carrp; + + /* + * Save original pointer for kfree() in case the + * driver is built as a module and can be unloaded. + */ + boardp->orig_reqp = reqp; + + adv_dvc_varp->carrier_buf = carrp; + + /* + * Point 'adv_reqp' to the request structures and + * link them together. + */ + req_cnt--; + reqp[req_cnt].next_reqp = NULL; + for (; req_cnt > 0; req_cnt--) { + reqp[req_cnt - 1].next_reqp = &reqp[req_cnt]; + } + boardp->adv_reqp = &reqp[0]; + + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + ASC_DBG(2, + "advansys_board_found: AdvInitAsc3550Driver()\n"); + warn_code = AdvInitAsc3550Driver(adv_dvc_varp); + } else if (adv_dvc_varp->chip_type == + ADV_CHIP_ASC38C0800) { + ASC_DBG(2, + "advansys_board_found: AdvInitAsc38C0800Driver()\n"); + warn_code = + AdvInitAsc38C0800Driver(adv_dvc_varp); + } else { + ASC_DBG(2, + "advansys_board_found: AdvInitAsc38C1600Driver()\n"); + warn_code = + AdvInitAsc38C1600Driver(adv_dvc_varp); + } + err_code = adv_dvc_varp->err_code; + + if (warn_code || err_code) { + ASC_PRINT3 + ("advansys_board_found: board %d error: warn 0x%x, error 0x%x\n", + boardp->id, warn_code, err_code); + } + } + } + + if (err_code != 0) { + release_region(shost->io_port, boardp->asc_n_io_port); + if (ASC_WIDE_BOARD(boardp)) { + iounmap(boardp->ioremap_addr); + kfree(boardp->orig_carrp); + boardp->orig_carrp = NULL; + if (boardp->orig_reqp) { + kfree(boardp->orig_reqp); + boardp->orig_reqp = boardp->adv_reqp = NULL; + } + while ((sgp = boardp->adv_sgblkp) != NULL) { + boardp->adv_sgblkp = sgp->next_sgblkp; + kfree(sgp); + } + } + if (shost->dma_channel != NO_ISA_DMA) { + free_dma(shost->dma_channel); + } +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + free_irq(shost->irq, boardp); + scsi_unregister(shost); + asc_board_count--; + return NULL; + } + ASC_DBG_PRT_SCSI_HOST(2, shost); + + return shost; +} + +/* + * advansys_detect() + * + * Detect function for AdvanSys adapters. + * + * Argument is a pointer to the host driver's scsi_hosts entry. + * + * Return number of adapters found. + * + * Note: Because this function is called during system initialization + * it must not call SCSI mid-level functions including scsi_malloc() + * and scsi_free(). + */ +static int __init advansys_detect(struct scsi_host_template *tpnt) +{ + static int detect_called = ASC_FALSE; + int iop; + int bus; + int ioport = 0; + struct device *dev = NULL; +#ifdef CONFIG_PCI + int pci_init_search = 0; + struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED]; + int pci_card_cnt_max = 0; + int pci_card_cnt = 0; + struct pci_dev *pdev = NULL; + int pci_device_id_cnt = 0; + unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { + PCI_DEVICE_ID_ASP_1200A, + PCI_DEVICE_ID_ASP_ABP940, + PCI_DEVICE_ID_ASP_ABP940U, + PCI_DEVICE_ID_ASP_ABP940UW, + PCI_DEVICE_ID_38C0800_REV1, + PCI_DEVICE_ID_38C1600_REV1 + }; +#endif /* CONFIG_PCI */ + + if (detect_called == ASC_FALSE) { + detect_called = ASC_TRUE; + } else { + printk + ("AdvanSys SCSI: advansys_detect() multiple calls ignored\n"); + return 0; + } + + ASC_DBG(1, "advansys_detect: begin\n"); + + asc_board_count = 0; + + /* + * If I/O port probing has been modified, then verify and + * clean-up the 'asc_ioport' list. + */ + if (asc_iopflag == ASC_TRUE) { + for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) { + ASC_DBG2(1, "advansys_detect: asc_ioport[%d] 0x%x\n", + ioport, asc_ioport[ioport]); + if (asc_ioport[ioport] != 0) { + for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; + iop++) { + if (_asc_def_iop_base[iop] == + asc_ioport[ioport]) { + break; + } + } + if (iop == ASC_IOADR_TABLE_MAX_IX) { + printk + ("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n", + asc_ioport[ioport]); + asc_ioport[ioport] = 0; + } + } + } + ioport = 0; + } + + for (bus = 0; bus < ASC_NUM_BUS; bus++) { + + ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n", + bus, asc_bus_name[bus]); + iop = 0; + + while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) { + + ASC_DBG1(2, "advansys_detect: asc_board_count %d\n", + asc_board_count); + + switch (asc_bus[bus]) { + case ASC_IS_ISA: + case ASC_IS_VL: +#ifdef CONFIG_ISA + if (asc_iopflag == ASC_FALSE) { + iop = + AscSearchIOPortAddr(iop, + asc_bus[bus]); + } else { + /* + * ISA and VL I/O port scanning has either been + * eliminated or limited to selected ports on + * the LILO command line, /etc/lilo.conf, or + * by setting variables when the module was loaded. + */ + ASC_DBG(1, + "advansys_detect: I/O port scanning modified\n"); + ioport_try_again: + iop = 0; + for (; ioport < ASC_NUM_IOPORT_PROBE; + ioport++) { + if ((iop = + asc_ioport[ioport]) != 0) { + break; + } + } + if (iop) { + ASC_DBG1(1, + "advansys_detect: probing I/O port 0x%x...\n", + iop); + 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. */ + asc_ioport[ioport] = 0; + goto ioport_try_again; + } else if (AscFindSignature(iop) + == ASC_FALSE) { + 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 { + /* + * If this isn't an ISA board, then it must be + * a VL board. If currently looking an ISA + * board is being looked for then try for + * another ISA board in 'asc_ioport'. + */ + if (asc_bus[bus] == + ASC_IS_ISA + && + (AscGetChipVersion + (iop, + ASC_IS_ISA) & + ASC_CHIP_VER_ISA_BIT) + == 0) { + /* + * Don't clear 'asc_ioport[ioport]'. Try + * this board again for VL. Increment + * 'ioport' past this board. + */ + ioport++; + release_region + (iop, + ASC_IOADR_GAP); + goto ioport_try_again; + } + } + /* + * This board appears good, don't try the I/O port + * again by clearing its value. Increment 'ioport' + * for the next iteration. + */ + asc_ioport[ioport++] = 0; + } + } +#endif /* CONFIG_ISA */ + break; + + case ASC_IS_EISA: +#ifdef CONFIG_ISA + iop = AscSearchIOPortAddr(iop, asc_bus[bus]); +#endif /* CONFIG_ISA */ + break; + + case ASC_IS_PCI: +#ifdef CONFIG_PCI + if (pci_init_search == 0) { + int i, j; + + pci_init_search = 1; + + /* Find all PCI cards. */ + while (pci_device_id_cnt < + ASC_PCI_DEVICE_ID_CNT) { + if ((pdev = + pci_find_device + (PCI_VENDOR_ID_ASP, + pci_device_id + [pci_device_id_cnt], + pdev)) == NULL) { + pci_device_id_cnt++; + } else { + if (pci_enable_device + (pdev) == 0) { + pci_devicep + [pci_card_cnt_max++] + = pdev; + } + } + } + + /* + * Sort PCI cards in ascending order by PCI Bus, Slot, + * and Device Number. + */ + for (i = 0; i < pci_card_cnt_max - 1; + i++) { + for (j = i + 1; + j < pci_card_cnt_max; + j++) { + if ((pci_devicep[j]-> + bus->number < + pci_devicep[i]-> + bus->number) + || + ((pci_devicep[j]-> + bus->number == + pci_devicep[i]-> + bus->number) + && + (pci_devicep[j]-> + devfn < + pci_devicep[i]-> + devfn))) { + pdev = + pci_devicep + [i]; + pci_devicep[i] = + pci_devicep + [j]; + pci_devicep[j] = + pdev; + } + } + } + + pci_card_cnt = 0; + } else { + pci_card_cnt++; + } + + if (pci_card_cnt == pci_card_cnt_max) { + iop = 0; + } else { + pdev = pci_devicep[pci_card_cnt]; + + ASC_DBG2(2, + "advansys_detect: devfn %d, bus number %d\n", + pdev->devfn, + pdev->bus->number); + iop = pci_resource_start(pdev, 0); + ASC_DBG2(1, + "advansys_detect: vendorID %X, deviceID %X\n", + pdev->vendor, + pdev->device); + ASC_DBG2(2, + "advansys_detect: iop %X, irqLine %d\n", + iop, pdev->irq); + } + if (pdev) + dev = &pdev->dev; + +#endif /* CONFIG_PCI */ + break; + + default: + ASC_PRINT1 + ("advansys_detect: unknown bus type: %d\n", + asc_bus[bus]); + break; + } + ASC_DBG1(1, "advansys_detect: iop 0x%x\n", iop); + + /* + * Adapter not found, try next bus type. + */ + if (iop == 0) { + break; + } + + advansys_board_found(iop, dev, asc_bus[bus]); + } + } + + ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", + asc_board_count); + return asc_board_count; +} + +/* + * advansys_release() + * + * Release resources allocated for a single AdvanSys adapter. + */ +static int advansys_release(struct Scsi_Host *shost) +{ + asc_board_t *boardp; + + ASC_DBG(1, "advansys_release: begin\n"); + boardp = ASC_BOARDP(shost); + free_irq(shost->irq, boardp); + if (shost->dma_channel != NO_ISA_DMA) { + ASC_DBG(1, "advansys_release: free_dma()\n"); + free_dma(shost->dma_channel); + } + release_region(shost->io_port, boardp->asc_n_io_port); + if (ASC_WIDE_BOARD(boardp)) { + adv_sgblk_t *sgp = NULL; + + iounmap(boardp->ioremap_addr); + kfree(boardp->orig_carrp); + boardp->orig_carrp = NULL; + if (boardp->orig_reqp) { + kfree(boardp->orig_reqp); + boardp->orig_reqp = boardp->adv_reqp = NULL; + } + while ((sgp = boardp->adv_sgblkp) != NULL) { + boardp->adv_sgblkp = sgp->next_sgblkp; + kfree(sgp); + } + } +#ifdef CONFIG_PROC_FS + ASC_ASSERT(boardp->prtbuf != NULL); + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + ASC_DBG(1, "advansys_release: end\n"); + return 0; +} + #ifdef CONFIG_PCI /* PCI Devices supported by this driver */ static struct pci_device_id advansys_pci_tbl[] __devinitdata = { - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { } + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {} }; + MODULE_DEVICE_TABLE(pci, advansys_pci_tbl); #endif /* CONFIG_PCI */ diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 85f2394ffc3..d30a30786dd 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -289,18 +289,18 @@ static LIST_HEAD(aha152x_host_list); if(spin_is_locked(&QLOCK)) { \ DPRINTK(debug_intr, DEBUG_LEAD "(%s:%d) already locked at %s:%d\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \ } \ - DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ + DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ spin_lock_irqsave(&QLOCK,flags); \ - DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) locked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ + DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ QLOCKER=__FUNCTION__; \ QLOCKERL=__LINE__; \ } while(0) #define DO_UNLOCK(flags) \ do { \ - DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) unlocking (locked at %s:%d)\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \ + DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocking (locked at %s:%d)\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \ spin_unlock_irqrestore(&QLOCK,flags); \ - DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) unlocked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ + DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ QLOCKER="(not locked)"; \ QLOCKERL=0; \ } while(0) @@ -322,6 +322,12 @@ static LIST_HEAD(aha152x_host_list); (cmd) ? ((cmd)->device->id & 0x0f) : -1, \ (cmd) ? ((cmd)->device->lun & 0x07) : -1 +static inline void +CMD_INC_RESID(struct scsi_cmnd *cmd, int inc) +{ + scsi_set_resid(cmd, scsi_get_resid(cmd) + inc); +} + #define DELAY_DEFAULT 1000 #if defined(PCMCIA) @@ -552,14 +558,11 @@ struct aha152x_hostdata { struct aha152x_scdata { Scsi_Cmnd *next; /* next sc in queue */ struct completion *done;/* semaphore to block on */ - unsigned char cmd_len; - unsigned char cmnd[MAX_COMMAND_SIZE]; - unsigned short use_sg; - unsigned request_bufflen; - void *request_buffer; + unsigned char aha_orig_cmd_len; + unsigned char aha_orig_cmnd[MAX_COMMAND_SIZE]; + int aha_orig_resid; }; - /* access macros for hostdata */ #define HOSTDATA(shpnt) ((struct aha152x_hostdata *) &shpnt->hostdata) @@ -978,15 +981,15 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete, #if defined(AHA152X_DEBUG) if (HOSTDATA(shpnt)->debug & debug_queue) { printk(INFO_LEAD "queue: %p; cmd_len=%d pieces=%d size=%u cmnd=", - CMDINFO(SCpnt), SCpnt, SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen); + CMDINFO(SCpnt), SCpnt, SCpnt->cmd_len, + scsi_sg_count(SCpnt), scsi_bufflen(SCpnt)); __scsi_print_command(SCpnt->cmnd); } #endif SCpnt->scsi_done = done; - SCpnt->resid = SCpnt->request_bufflen; SCpnt->SCp.phase = not_issued | phase; - SCpnt->SCp.Status = CHECK_CONDITION; + SCpnt->SCp.Status = 0x1; /* Ilegal status by SCSI standard */ SCpnt->SCp.Message = 0; SCpnt->SCp.have_data_in = 0; SCpnt->SCp.sent_command = 0; @@ -997,20 +1000,11 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete, return FAILED; } } else { - struct aha152x_scdata *sc; - SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC); if(SCpnt->host_scribble==0) { printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt)); return FAILED; } - - sc = SCDATA(SCpnt); - memcpy(sc->cmnd, SCpnt->cmnd, sizeof(sc->cmnd)); - sc->request_buffer = SCpnt->request_buffer; - sc->request_bufflen = SCpnt->request_bufflen; - sc->use_sg = SCpnt->use_sg; - sc->cmd_len = SCpnt->cmd_len; } SCNEXT(SCpnt) = NULL; @@ -1022,16 +1016,25 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete, SCp.buffer : next buffer SCp.buffers_residual : left buffers in list SCp.phase : current state of the command */ - if (SCpnt->use_sg) { - SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; - SCpnt->SCp.ptr = SG_ADDRESS(SCpnt->SCp.buffer); - SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; - SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; - } else { - SCpnt->SCp.ptr = (char *) SCpnt->request_buffer; - SCpnt->SCp.this_residual = SCpnt->request_bufflen; + + if ((phase & (check_condition|resetting)) || !scsi_sglist(SCpnt)) { + if (phase & check_condition) { + SCpnt->SCp.ptr = SCpnt->sense_buffer; + SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer); + scsi_set_resid(SCpnt, sizeof(SCpnt->sense_buffer)); + } else { + SCpnt->SCp.ptr = NULL; + SCpnt->SCp.this_residual = 0; + scsi_set_resid(SCpnt, 0); + } SCpnt->SCp.buffer = NULL; SCpnt->SCp.buffers_residual = 0; + } else { + scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); + SCpnt->SCp.buffer = scsi_sglist(SCpnt); + SCpnt->SCp.ptr = SG_ADDRESS(SCpnt->SCp.buffer); + SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; + SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1; } DO_LOCK(flags); @@ -1150,9 +1153,6 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) DECLARE_COMPLETION(done); int ret, issued, disconnected; unsigned char old_cmd_len = SCpnt->cmd_len; - unsigned short old_use_sg = SCpnt->use_sg; - void *old_buffer = SCpnt->request_buffer; - unsigned old_bufflen = SCpnt->request_bufflen; unsigned long flags; unsigned long timeleft; @@ -1174,9 +1174,6 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) DO_UNLOCK(flags); SCpnt->cmd_len = 0; - SCpnt->use_sg = 0; - SCpnt->request_buffer = NULL; - SCpnt->request_bufflen = 0; aha152x_internal_queue(SCpnt, &done, resetting, reset_done); @@ -1189,9 +1186,6 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt) } SCpnt->cmd_len = old_cmd_len; - SCpnt->use_sg = old_use_sg; - SCpnt->request_buffer = old_buffer; - SCpnt->request_bufflen = old_bufflen; DO_LOCK(flags); @@ -1531,8 +1525,8 @@ static void busfree_run(struct Scsi_Host *shpnt) /* target sent DISCONNECT */ DPRINTK(debug_selection, DEBUG_LEAD "target disconnected at %d/%d\n", CMDINFO(CURRENT_SC), - CURRENT_SC->resid, - CURRENT_SC->request_bufflen); + scsi_get_resid(CURRENT_SC), + scsi_bufflen(CURRENT_SC)); #if defined(AHA152X_STAT) HOSTDATA(shpnt)->disconnections++; #endif @@ -1568,18 +1562,16 @@ static void busfree_run(struct Scsi_Host *shpnt) #endif /* restore old command */ - memcpy(cmd->cmnd, sc->cmnd, sizeof(sc->cmnd)); - cmd->request_buffer = sc->request_buffer; - cmd->request_bufflen = sc->request_bufflen; - cmd->use_sg = sc->use_sg; - cmd->cmd_len = sc->cmd_len; + memcpy(cmd->cmnd, sc->aha_orig_cmnd, sizeof(cmd->cmnd)); + cmd->cmd_len = sc->aha_orig_cmd_len; + scsi_set_resid(cmd, sc->aha_orig_resid); - cmd->SCp.Status = 0x02; + cmd->SCp.Status = SAM_STAT_CHECK_CONDITION; HOSTDATA(shpnt)->commands--; if (!HOSTDATA(shpnt)->commands) SETPORT(PORTA, 0); /* turn led off */ - } else if(DONE_SC->SCp.Status==0x02) { + } else if(DONE_SC->SCp.Status==SAM_STAT_CHECK_CONDITION) { #if defined(AHA152X_STAT) HOSTDATA(shpnt)->busfree_with_check_condition++; #endif @@ -1587,13 +1579,23 @@ static void busfree_run(struct Scsi_Host *shpnt) DPRINTK(debug_eh, ERR_LEAD "CHECK CONDITION found\n", CMDINFO(DONE_SC)); #endif - if(!(DONE_SC->SCp.Status & not_issued)) { + if(!(DONE_SC->SCp.phase & not_issued)) { + struct aha152x_scdata *sc; Scsi_Cmnd *ptr = DONE_SC; DONE_SC=NULL; #if 0 DPRINTK(debug_eh, ERR_LEAD "requesting sense\n", CMDINFO(ptr)); #endif + /* save old command */ + sc = SCDATA(ptr); + /* It was allocated in aha152x_internal_queue? */ + BUG_ON(!sc); + memcpy(sc->aha_orig_cmnd, ptr->cmnd, + sizeof(ptr->cmnd)); + sc->aha_orig_cmd_len = ptr->cmd_len; + sc->aha_orig_resid = scsi_get_resid(ptr); + ptr->cmnd[0] = REQUEST_SENSE; ptr->cmnd[1] = 0; ptr->cmnd[2] = 0; @@ -1601,10 +1603,7 @@ static void busfree_run(struct Scsi_Host *shpnt) ptr->cmnd[4] = sizeof(ptr->sense_buffer); ptr->cmnd[5] = 0; ptr->cmd_len = 6; - ptr->use_sg = 0; - ptr->request_buffer = ptr->sense_buffer; - ptr->request_bufflen = sizeof(ptr->sense_buffer); - + DO_UNLOCK(flags); aha152x_internal_queue(ptr, NULL, check_condition, ptr->scsi_done); DO_LOCK(flags); @@ -2180,7 +2179,8 @@ static void datai_init(struct Scsi_Host *shpnt) DATA_LEN=0; DPRINTK(debug_datai, DEBUG_LEAD "datai_init: request_bufflen=%d resid=%d\n", - CMDINFO(CURRENT_SC), CURRENT_SC->request_bufflen, CURRENT_SC->resid); + CMDINFO(CURRENT_SC), scsi_bufflen(CURRENT_SC), + scsi_get_resid(CURRENT_SC)); } static void datai_run(struct Scsi_Host *shpnt) @@ -2293,11 +2293,12 @@ static void datai_run(struct Scsi_Host *shpnt) static void datai_end(struct Scsi_Host *shpnt) { - CURRENT_SC->resid -= GETSTCNT(); + CMD_INC_RESID(CURRENT_SC, -GETSTCNT()); DPRINTK(debug_datai, DEBUG_LEAD "datai_end: request_bufflen=%d resid=%d stcnt=%d\n", - CMDINFO(CURRENT_SC), CURRENT_SC->request_bufflen, CURRENT_SC->resid, GETSTCNT()); + CMDINFO(CURRENT_SC), scsi_bufflen(CURRENT_SC), + scsi_get_resid(CURRENT_SC), GETSTCNT()); SETPORT(SXFRCTL0, CH1|CLRSTCNT); SETPORT(DMACNTRL0, 0); @@ -2318,11 +2319,12 @@ static void datao_init(struct Scsi_Host *shpnt) SETPORT(SIMODE0, 0); SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE ); - DATA_LEN = CURRENT_SC->resid; + DATA_LEN = scsi_get_resid(CURRENT_SC); DPRINTK(debug_datao, DEBUG_LEAD "datao_init: request_bufflen=%d; resid=%d\n", - CMDINFO(CURRENT_SC), CURRENT_SC->request_bufflen, CURRENT_SC->resid); + CMDINFO(CURRENT_SC), scsi_bufflen(CURRENT_SC), + scsi_get_resid(CURRENT_SC)); } static void datao_run(struct Scsi_Host *shpnt) @@ -2346,7 +2348,7 @@ static void datao_run(struct Scsi_Host *shpnt) SETPORT(DMACNTRL0,WRITE_READ|ENDMA|_8BIT); SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++); CURRENT_SC->SCp.this_residual--; - CURRENT_SC->resid--; + CMD_INC_RESID(CURRENT_SC, -1); SETPORT(DMACNTRL0,WRITE_READ|ENDMA); } @@ -2355,7 +2357,7 @@ static void datao_run(struct Scsi_Host *shpnt) outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); CURRENT_SC->SCp.ptr += 2 * data_count; CURRENT_SC->SCp.this_residual -= 2 * data_count; - CURRENT_SC->resid -= 2 * data_count; + CMD_INC_RESID(CURRENT_SC, -2 * data_count); } if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) { @@ -2381,35 +2383,34 @@ static void datao_run(struct Scsi_Host *shpnt) static void datao_end(struct Scsi_Host *shpnt) { if(TESTLO(DMASTAT, DFIFOEMP)) { - int data_count = (DATA_LEN - CURRENT_SC->resid) - GETSTCNT(); + int data_count = (DATA_LEN - scsi_get_resid(CURRENT_SC)) - + GETSTCNT(); DPRINTK(debug_datao, DEBUG_LEAD "datao: %d bytes to resend (%d written, %d transferred)\n", CMDINFO(CURRENT_SC), data_count, - DATA_LEN-CURRENT_SC->resid, + DATA_LEN - scsi_get_resid(CURRENT_SC), GETSTCNT()); - CURRENT_SC->resid += data_count; + CMD_INC_RESID(CURRENT_SC, data_count); - if(CURRENT_SC->use_sg) { - data_count -= CURRENT_SC->SCp.ptr - SG_ADDRESS(CURRENT_SC->SCp.buffer); - while(data_count>0) { - CURRENT_SC->SCp.buffer--; - CURRENT_SC->SCp.buffers_residual++; - data_count -= CURRENT_SC->SCp.buffer->length; - } - CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer) - data_count; - CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length + data_count; - } else { - CURRENT_SC->SCp.ptr -= data_count; - CURRENT_SC->SCp.this_residual += data_count; + data_count -= CURRENT_SC->SCp.ptr - + SG_ADDRESS(CURRENT_SC->SCp.buffer); + while(data_count>0) { + CURRENT_SC->SCp.buffer--; + CURRENT_SC->SCp.buffers_residual++; + data_count -= CURRENT_SC->SCp.buffer->length; } + CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer) - + data_count; + CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length + + data_count; } DPRINTK(debug_datao, DEBUG_LEAD "datao_end: request_bufflen=%d; resid=%d; stcnt=%d\n", CMDINFO(CURRENT_SC), - CURRENT_SC->request_bufflen, - CURRENT_SC->resid, + scsi_bufflen(CURRENT_SC), + scsi_get_resid(CURRENT_SC), GETSTCNT()); SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT); @@ -2936,7 +2937,7 @@ static void show_command(Scsi_Cmnd *ptr) __scsi_print_command(ptr->cmnd); printk(KERN_DEBUG "); request_bufflen=%d; resid=%d; phase |", - ptr->request_bufflen, ptr->resid); + scsi_bufflen(ptr), scsi_get_resid(ptr)); if (ptr->SCp.phase & not_issued) printk("not issued|"); @@ -3006,7 +3007,8 @@ static int get_command(char *pos, Scsi_Cmnd * ptr) SPRINTF("0x%02x ", ptr->cmnd[i]); SPRINTF("); resid=%d; residual=%d; buffers=%d; phase |", - ptr->resid, ptr->SCp.this_residual, ptr->SCp.buffers_residual); + scsi_get_resid(ptr), ptr->SCp.this_residual, + ptr->SCp.buffers_residual); if (ptr->SCp.phase & not_issued) SPRINTF("not issued|"); @@ -3395,7 +3397,7 @@ static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start PDEBUG(debug_datai, "data in"); PDEBUG(debug_datao, "data out"); PDEBUG(debug_eh, "eh"); - PDEBUG(debug_locks, "locks"); + PDEBUG(debug_locking, "locks"); PDEBUG(debug_phases, "phases"); SPRINTF("\n"); @@ -3474,6 +3476,12 @@ static int aha152x_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start return thislength < length ? thislength : length; } +static int aha152x_adjust_queue(struct scsi_device *device) +{ + blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH); + return 0; +} + static struct scsi_host_template aha152x_driver_template = { .module = THIS_MODULE, .name = AHA152X_REVID, @@ -3490,6 +3498,7 @@ static struct scsi_host_template aha152x_driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, + .slave_alloc = aha152x_adjust_queue, }; #if !defined(PCMCIA) diff --git a/drivers/scsi/aha152x.h b/drivers/scsi/aha152x.h index d2add24d02a..ac4bfa438bf 100644 --- a/drivers/scsi/aha152x.h +++ b/drivers/scsi/aha152x.h @@ -298,7 +298,7 @@ typedef union { enum { debug_procinfo = 0x0001, debug_queue = 0x0002, - debug_locks = 0x0004, + debug_locking = 0x0004, debug_intr = 0x0008, debug_selection = 0x0010, debug_msgo = 0x0020, diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 286ab83116f..a055a96e3ad 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -2284,9 +2284,12 @@ static void ahd_linux_set_period(struct scsi_target *starget, int period) if (period < 8) period = 8; if (period < 10) { - ppr_options |= MSG_EXT_PPR_DT_REQ; - if (period == 8) - ppr_options |= MSG_EXT_PPR_IU_REQ; + if (spi_max_width(starget)) { + ppr_options |= MSG_EXT_PPR_DT_REQ; + if (period == 8) + ppr_options |= MSG_EXT_PPR_IU_REQ; + } else + period = 10; } dt = ppr_options & MSG_EXT_PPR_DT_REQ; @@ -2365,7 +2368,7 @@ static void ahd_linux_set_dt(struct scsi_target *starget, int dt) printf("%s: %s DT\n", ahd_name(ahd), dt ? "enabling" : "disabling"); #endif - if (dt) { + if (dt && spi_max_width(starget)) { ppr_options |= MSG_EXT_PPR_DT_REQ; if (!width) ahd_linux_set_width(starget, 1); @@ -2447,7 +2450,7 @@ static void ahd_linux_set_iu(struct scsi_target *starget, int iu) iu ? "enabling" : "disabling"); #endif - if (iu) { + if (iu && spi_max_width(starget)) { ppr_options |= MSG_EXT_PPR_IU_REQ; ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */ } @@ -2487,7 +2490,7 @@ static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm) rdstrm ? "enabling" : "disabling"); #endif - if (rdstrm) + if (rdstrm && spi_max_width(starget)) ppr_options |= MSG_EXT_PPR_RD_STRM; ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, @@ -2523,7 +2526,7 @@ static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow) wrflow ? "enabling" : "disabling"); #endif - if (wrflow) + if (wrflow && spi_max_width(starget)) ppr_options |= MSG_EXT_PPR_WR_FLOW; ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, @@ -2567,7 +2570,7 @@ static void ahd_linux_set_rti(struct scsi_target *starget, int rti) rti ? "enabling" : "disabling"); #endif - if (rti) + if (rti && spi_max_width(starget)) ppr_options |= MSG_EXT_PPR_RTI; ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, @@ -2603,7 +2606,7 @@ static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp) pcomp ? "Enable" : "Disable"); #endif - if (pcomp) { + if (pcomp && spi_max_width(starget)) { uint8_t precomp; if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { @@ -2647,7 +2650,7 @@ static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold) unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ; unsigned long flags; - if (hold) + if (hold && spi_max_width(starget)) ppr_options |= MSG_EXT_PPR_HOLD_MCS; ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 75733b09f27..f350b5e89e7 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -1701,7 +1701,16 @@ ahc_find_syncrate(struct ahc_softc *ahc, u_int *period, if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0 && maxsync < AHC_SYNCRATE_ULTRA2) maxsync = AHC_SYNCRATE_ULTRA2; - + + /* Now set the maxsync based on the card capabilities + * DT is already done above */ + if ((ahc->features & (AHC_DT | AHC_ULTRA2)) == 0 + && maxsync < AHC_SYNCRATE_ULTRA) + maxsync = AHC_SYNCRATE_ULTRA; + if ((ahc->features & (AHC_DT | AHC_ULTRA2 | AHC_ULTRA)) == 0 + && maxsync < AHC_SYNCRATE_FAST) + maxsync = AHC_SYNCRATE_FAST; + for (syncrate = &ahc_syncrates[maxsync]; syncrate->rate != NULL; syncrate++) { @@ -1765,6 +1774,17 @@ ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync) else scsirate &= SXFR; + /* now set maxsync based on card capabilities */ + if ((ahc->features & AHC_DT) == 0 && maxsync < AHC_SYNCRATE_ULTRA2) + maxsync = AHC_SYNCRATE_ULTRA2; + if ((ahc->features & (AHC_DT | AHC_ULTRA2)) == 0 + && maxsync < AHC_SYNCRATE_ULTRA) + maxsync = AHC_SYNCRATE_ULTRA; + if ((ahc->features & (AHC_DT | AHC_ULTRA2 | AHC_ULTRA)) == 0 + && maxsync < AHC_SYNCRATE_FAST) + maxsync = AHC_SYNCRATE_FAST; + + syncrate = &ahc_syncrates[maxsync]; while (syncrate->rate != NULL) { diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 1803ab6fc21..2e9c38f2e8a 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -2317,8 +2317,13 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period) if (period < 9) period = 9; /* 12.5ns is our minimum */ - if (period == 9) - ppr_options |= MSG_EXT_PPR_DT_REQ; + if (period == 9) { + if (spi_max_width(starget)) + ppr_options |= MSG_EXT_PPR_DT_REQ; + else + /* need wide for DT and need DT for 12.5 ns */ + period = 10; + } ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); @@ -2381,7 +2386,7 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt) unsigned long flags; struct ahc_syncrate *syncrate; - if (dt) { + if (dt && spi_max_width(starget)) { ppr_options |= MSG_EXT_PPR_DT_REQ; if (!width) ahc_linux_set_width(starget, 1); diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c index c520e5b41fb..3dce618bf41 100644 --- a/drivers/scsi/aic94xx/aic94xx_dev.c +++ b/drivers/scsi/aic94xx/aic94xx_dev.c @@ -126,7 +126,7 @@ static inline int asd_init_sata(struct domain_device *dev) if (w76 & 0x100) /* NCQ? */ qdepth = (w75 & 0x1F) + 1; asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, - (1<<qdepth)-1); + (1ULL<<qdepth)-1); asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth); } if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM || diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 1c0d7578e79..63bcde24644 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -81,6 +81,9 @@ static struct scsi_host_template aic94xx_sht = { .use_clustering = ENABLE_CLUSTERING, .eh_device_reset_handler = sas_eh_device_reset_handler, .eh_bus_reset_handler = sas_eh_bus_reset_handler, + .slave_alloc = sas_slave_alloc, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, }; static int __devinit asd_map_memio(struct asd_ha_struct *asd_ha) @@ -462,7 +465,7 @@ static int asd_create_global_caches(void) sizeof(struct asd_dma_tok), 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); + NULL); if (!asd_dma_token_cache) { asd_printk("couldn't create dma token cache\n"); return -ENOMEM; @@ -474,7 +477,7 @@ static int asd_create_global_caches(void) sizeof(struct asd_ascb), 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); + NULL); if (!asd_ascb_cache) { asd_printk("couldn't create ascb cache\n"); goto Err; @@ -583,7 +586,7 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, goto Err; } asd_ha->pcidev = dev; - asd_ha->sas_ha.pcidev = asd_ha->pcidev; + asd_ha->sas_ha.dev = &asd_ha->pcidev->dev; asd_ha->sas_ha.lldd_ha = asd_ha; asd_ha->name = asd_dev->name; @@ -602,8 +605,6 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, goto Err_free; } - - err = asd_dev->setup(asd_ha); if (err) goto Err_free; diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index e2ad5bed940..ab13824df85 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -74,8 +74,13 @@ static inline int asd_map_scatterlist(struct sas_task *task, return 0; } - num_sg = pci_map_sg(asd_ha->pcidev, task->scatter, task->num_scatter, - task->data_dir); + /* STP tasks come from libata which has already mapped + * the SG list */ + if (sas_protocol_ata(task->task_proto)) + num_sg = task->num_scatter; + else + num_sg = pci_map_sg(asd_ha->pcidev, task->scatter, + task->num_scatter, task->data_dir); if (num_sg == 0) return -ENOMEM; @@ -120,8 +125,9 @@ static inline int asd_map_scatterlist(struct sas_task *task, return 0; err_unmap: - pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, - task->data_dir); + if (sas_protocol_ata(task->task_proto)) + pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, + task->data_dir); return res; } @@ -142,8 +148,9 @@ static inline void asd_unmap_scatterlist(struct asd_ascb *ascb) } asd_free_coherent(asd_ha, ascb->sg_arr); - pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, - task->data_dir); + if (task->task_proto != SAS_PROTOCOL_STP) + pci_unmap_sg(asd_ha->pcidev, task->scatter, task->num_scatter, + task->data_dir); } /* ---------- Task complete tasklet ---------- */ @@ -391,7 +398,6 @@ static int asd_build_ata_ascb(struct asd_ascb *ascb, struct sas_task *task, scb->ata_task.total_xfer_len = cpu_to_le32(task->total_xfer_len); scb->ata_task.fis = task->ata_task.fis; - scb->ata_task.fis.fis_type = 0x27; if (likely(!task->ata_task.device_control_reg_update)) scb->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */ scb->ata_task.fis.flags &= 0xF0; /* PM_PORT field shall be 0 */ @@ -445,7 +451,7 @@ static int asd_build_smp_ascb(struct asd_ascb *ascb, struct sas_task *task, struct scb *scb; pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_req, 1, - PCI_DMA_FROMDEVICE); + PCI_DMA_TODEVICE); pci_map_sg(asd_ha->pcidev, &task->smp_task.smp_resp, 1, PCI_DMA_FROMDEVICE); @@ -480,7 +486,7 @@ static void asd_unbuild_smp_ascb(struct asd_ascb *a) BUG_ON(!task); pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_req, 1, - PCI_DMA_FROMDEVICE); + PCI_DMA_TODEVICE); pci_unmap_sg(a->ha->pcidev, &task->smp_task.smp_resp, 1, PCI_DMA_FROMDEVICE); } diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig index d006a8cb4a7..7236143941f 100644 --- a/drivers/scsi/arm/Kconfig +++ b/drivers/scsi/arm/Kconfig @@ -74,15 +74,6 @@ config SCSI_CUMANA_1 This enables support for the Cumana SCSI I card. If you have an Acorn system with one of these, say Y. If unsure, say N. -config SCSI_ECOSCSI - tristate "EcoScsi support (EXPERIMENTAL)" - depends on ARCH_ACORN && EXPERIMENTAL && (ARCH_ARC || ARCH_A5K) && SCSI - select SCSI_SPI_ATTRS - help - This enables support for the EcoSCSI card -- a small card that sits - in the Econet socket. If you have an Acorn system with one of these, - say Y. If unsure, say N. - config SCSI_OAK1 tristate "Oak SCSI support (EXPERIMENTAL)" depends on ARCH_ACORN && EXPERIMENTAL && SCSI diff --git a/drivers/scsi/arm/Makefile b/drivers/scsi/arm/Makefile index e8db17924c1..16c3e86a6b1 100644 --- a/drivers/scsi/arm/Makefile +++ b/drivers/scsi/arm/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_SCSI_ACORNSCSI_3) += acornscsi_mod.o queue.o msgqueue.o obj-$(CONFIG_SCSI_ARXESCSI) += arxescsi.o fas216.o queue.o msgqueue.o obj-$(CONFIG_SCSI_CUMANA_1) += cumana_1.o obj-$(CONFIG_SCSI_CUMANA_2) += cumana_2.o fas216.o queue.o msgqueue.o -obj-$(CONFIG_SCSI_ECOSCSI) += ecoscsi.o obj-$(CONFIG_SCSI_OAK1) += oak.o obj-$(CONFIG_SCSI_POWERTECSCSI) += powertec.o fas216.o queue.o msgqueue.o obj-$(CONFIG_SCSI_EESOXSCSI) += eesox.o fas216.o queue.o msgqueue.o diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index cf9a21cea6d..49d838e90a2 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -24,7 +24,7 @@ #define CUMANASCSI_PUBLIC_RELEASE 1 -#define NCR5380_implementation_fields int port, ctrl +#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) #define NCR5380_local_declare() struct Scsi_Host *_instance #define NCR5380_setup(instance) _instance = instance #define NCR5380_read(reg) cumanascsi_read(_instance, reg) @@ -33,6 +33,11 @@ #define NCR5380_queue_command cumanascsi_queue_command #define NCR5380_proc_info cumanascsi_proc_info +#define NCR5380_implementation_fields \ + unsigned ctrl; \ + void __iomem *base; \ + void __iomem *dma + #define BOARD_NORMAL 0 #define BOARD_NCR53C400 1 @@ -47,192 +52,162 @@ const char *cumanascsi_info(struct Scsi_Host *spnt) return ""; } -#ifdef NOT_EFFICIENT -#define CTRL(p,v) outb(*ctrl = (v), (p) - 577) -#define STAT(p) inb((p)+1) -#define IN(p) inb((p)) -#define OUT(v,p) outb((v), (p)) -#else -#define CTRL(p,v) (p[-2308] = (*ctrl = (v))) -#define STAT(p) (p[4]) -#define IN(p) (*(p)) -#define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p))) -#define OUT(v,p) (*(p) = (v)) -#define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v)) -#endif -#define L(v) (((v)<<16)|((v) & 0x0000ffff)) -#define H(v) (((v)>>16)|((v) & 0xffff0000)) +#define CTRL 0x16fc +#define STAT 0x2004 +#define L(v) (((v)<<16)|((v) & 0x0000ffff)) +#define H(v) (((v)>>16)|((v) & 0xffff0000)) static inline int -NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len) +NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, int len) { - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; - int oldctrl = *ctrl; unsigned long *laddr; -#ifdef NOT_EFFICIENT - int iobase = instance->io_port; - int dma_io = iobase & ~(0x3C0000>>2); -#else - volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); - volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000); -#endif + void __iomem *dma = priv(host)->dma + 0x2000; if(!len) return 0; - CTRL(iobase, 0x02); + writeb(0x02, priv(host)->base + CTRL); laddr = (unsigned long *)addr; while(len >= 32) { - int status; + unsigned int status; unsigned long v; - status = STAT(iobase); + status = readb(priv(host)->base + STAT); if(status & 0x80) goto end; if(!(status & 0x40)) continue; - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); + v=*laddr++; writew(L(v), dma); writew(H(v), dma); + v=*laddr++; writew(L(v), dma); writew(H(v), dma); + v=*laddr++; writew(L(v), dma); writew(H(v), dma); + v=*laddr++; writew(L(v), dma); writew(H(v), dma); + v=*laddr++; writew(L(v), dma); writew(H(v), dma); + v=*laddr++; writew(L(v), dma); writew(H(v), dma); + v=*laddr++; writew(L(v), dma); writew(H(v), dma); + v=*laddr++; writew(L(v), dma); writew(H(v), dma); len -= 32; if(len == 0) break; } addr = (unsigned char *)laddr; - CTRL(iobase, 0x12); + writeb(0x12, priv(host)->base + CTRL); + while(len > 0) { - int status; - status = STAT(iobase); + unsigned int status; + status = readb(priv(host)->base + STAT); if(status & 0x80) goto end; if(status & 0x40) { - OUT(*addr++, dma_io); + writeb(*addr++, dma); if(--len == 0) break; } - status = STAT(iobase); + status = readb(priv(host)->base + STAT); if(status & 0x80) goto end; if(status & 0x40) { - OUT(*addr++, dma_io); + writeb(*addr++, dma); if(--len == 0) break; } } end: - CTRL(iobase, oldctrl|0x40); + writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); return len; } static inline int -NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, int len) +NCR5380_pread(struct Scsi_Host *host, unsigned char *addr, int len) { - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; - int oldctrl = *ctrl; unsigned long *laddr; -#ifdef NOT_EFFICIENT - int iobase = instance->io_port; - int dma_io = iobase & ~(0x3C0000>>2); -#else - volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); - volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000); -#endif + void __iomem *dma = priv(host)->dma + 0x2000; if(!len) return 0; - CTRL(iobase, 0x00); + writeb(0x00, priv(host)->base + CTRL); laddr = (unsigned long *)addr; while(len >= 32) { - int status; - status = STAT(iobase); + unsigned int status; + status = readb(priv(host)->base + STAT); if(status & 0x80) goto end; if(!(status & 0x40)) continue; - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); + *laddr++ = readw(dma) | (readw(dma) << 16); + *laddr++ = readw(dma) | (readw(dma) << 16); + *laddr++ = readw(dma) | (readw(dma) << 16); + *laddr++ = readw(dma) | (readw(dma) << 16); + *laddr++ = readw(dma) | (readw(dma) << 16); + *laddr++ = readw(dma) | (readw(dma) << 16); + *laddr++ = readw(dma) | (readw(dma) << 16); + *laddr++ = readw(dma) | (readw(dma) << 16); len -= 32; if(len == 0) break; } addr = (unsigned char *)laddr; - CTRL(iobase, 0x10); + writeb(0x10, priv(host)->base + CTRL); + while(len > 0) { - int status; - status = STAT(iobase); + unsigned int status; + status = readb(priv(host)->base + STAT); if(status & 0x80) goto end; if(status & 0x40) { - *addr++ = IN(dma_io); + *addr++ = readb(dma); if(--len == 0) break; } - status = STAT(iobase); + status = readb(priv(host)->base + STAT); if(status & 0x80) goto end; if(status & 0x40) { - *addr++ = IN(dma_io); + *addr++ = readb(dma); if(--len == 0) break; } } end: - CTRL(iobase, oldctrl|0x40); + writeb(priv(host)->ctrl | 0x40, priv(host)->base + CTRL); return len; } -#undef STAT -#undef CTRL -#undef IN -#undef OUT +static unsigned char cumanascsi_read(struct Scsi_Host *host, unsigned int reg) +{ + void __iomem *base = priv(host)->base; + unsigned char val; -#define CTRL(p,v) outb(*ctrl = (v), (p) - 577) + writeb(0, base + CTRL); -static char cumanascsi_read(struct Scsi_Host *instance, int reg) -{ - unsigned int iobase = instance->io_port; - int i; - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; + val = readb(base + 0x2100 + (reg << 2)); - CTRL(iobase, 0); - i = inb(iobase + 64 + reg); - CTRL(iobase, 0x40); + priv(host)->ctrl = 0x40; + writeb(0x40, base + CTRL); - return i; + return val; } -static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value) +static void cumanascsi_write(struct Scsi_Host *host, unsigned int reg, unsigned int value) { - int iobase = instance->io_port; - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; + void __iomem *base = priv(host)->base; - CTRL(iobase, 0); - outb(value, iobase + 64 + reg); - CTRL(iobase, 0x40); -} + writeb(0, base + CTRL); -#undef CTRL + writeb(value, base + 0x2100 + (reg << 2)); + + priv(host)->ctrl = 0x40; + writeb(0x40, base + CTRL); +} #include "../NCR5380.c" @@ -256,32 +231,46 @@ static int __devinit cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id) { struct Scsi_Host *host; - int ret = -ENOMEM; + int ret; - host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata)); - if (!host) + ret = ecard_request_resources(ec); + if (ret) goto out; - host->io_port = ecard_address(ec, ECARD_IOC, ECARD_SLOW) + 0x800; + host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata)); + if (!host) { + ret = -ENOMEM; + goto out_release; + } + + priv(host)->base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCSLOW), + ecard_resource_len(ec, ECARD_RES_IOCSLOW)); + priv(host)->dma = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), + ecard_resource_len(ec, ECARD_RES_MEMC)); + if (!priv(host)->base || !priv(host)->dma) { + ret = -ENOMEM; + goto out_unmap; + } + host->irq = ec->irq; NCR5380_init(host, 0); + priv(host)->ctrl = 0; + writeb(0, priv(host)->base + CTRL); + host->n_io_port = 255; if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) { ret = -EBUSY; - goto out_free; + goto out_unmap; } - ((struct NCR5380_hostdata *)host->hostdata)->ctrl = 0; - outb(0x00, host->io_port - 577); - ret = request_irq(host->irq, cumanascsi_intr, IRQF_DISABLED, "CumanaSCSI-1", host); if (ret) { printk("scsi%d: IRQ%d not free: %d\n", host->host_no, host->irq, ret); - goto out_release; + goto out_unmap; } printk("scsi%d: at port 0x%08lx irq %d", @@ -301,10 +290,12 @@ cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id) out_free_irq: free_irq(host->irq, host); - out_release: - release_region(host->io_port, host->n_io_port); - out_free: + out_unmap: + iounmap(priv(host)->base); + iounmap(priv(host)->dma); scsi_host_put(host); + out_release: + ecard_release_resources(ec); out: return ret; } @@ -318,8 +309,10 @@ static void __devexit cumanascsi1_remove(struct expansion_card *ec) scsi_remove_host(host); free_irq(host->irq, host); NCR5380_exit(host); - release_region(host->io_port, host->n_io_port); + iounmap(priv(host)->base); + iounmap(priv(host)->dma); scsi_host_put(host); + ecard_release_resources(ec); } static const struct ecard_id cumanascsi1_cids[] = { diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c deleted file mode 100644 index 378e7af0c5d..00000000000 --- a/drivers/scsi/arm/ecoscsi.c +++ /dev/null @@ -1,236 +0,0 @@ -#define AUTOSENSE -/* #define PSEUDO_DMA */ - -/* - * EcoSCSI Generic NCR5380 driver - * - * Copyright 1995, Russell King - * - * ALPHA RELEASE 1. - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -#include <linux/module.h> -#include <linux/signal.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/blkdev.h> - -#include <asm/io.h> -#include <asm/system.h> - -#include "../scsi.h" -#include <scsi/scsi_host.h> - -#define NCR5380_implementation_fields int port, ctrl -#define NCR5380_local_declare() struct Scsi_Host *_instance -#define NCR5380_setup(instance) _instance = instance - -#define NCR5380_read(reg) ecoscsi_read(_instance, reg) -#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value) - -#define NCR5380_intr ecoscsi_intr -#define NCR5380_queue_command ecoscsi_queue_command -#define NCR5380_proc_info ecoscsi_proc_info - -#include "../NCR5380.h" - -#define ECOSCSI_PUBLIC_RELEASE 1 - -static char ecoscsi_read(struct Scsi_Host *instance, int reg) -{ - int iobase = instance->io_port; - outb(reg | 8, iobase); - return inb(iobase + 1); -} - -static void ecoscsi_write(struct Scsi_Host *instance, int reg, int value) -{ - int iobase = instance->io_port; - outb(reg | 8, iobase); - outb(value, iobase + 1); -} - -/* - * Function : ecoscsi_setup(char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer parameters with ints[0] - * equal to the number of ints. - * - */ - -void ecoscsi_setup(char *str, int *ints) -{ -} - -const char * ecoscsi_info (struct Scsi_Host *spnt) -{ - return ""; -} - -#if 0 -#define STAT(p) inw(p + 144) - -static inline int NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, - int len) -{ - int iobase = host->io_port; -printk("writing %p len %d\n",addr, len); - if(!len) return -1; - - while(1) - { - int status; - while(((status = STAT(iobase)) & 0x100)==0); - } -} - -static inline int NCR5380_pread(struct Scsi_Host *host, unsigned char *addr, - int len) -{ - int iobase = host->io_port; - int iobase2= host->io_port + 0x100; - unsigned char *start = addr; - int s; -printk("reading %p len %d\n",addr, len); - outb(inb(iobase + 128), iobase + 135); - while(len > 0) - { - int status,b,i, timeout; - timeout = 0x07FFFFFF; - while(((status = STAT(iobase)) & 0x100)==0) - { - timeout--; - if(status & 0x200 || !timeout) - { - printk("status = %p\n",status); - outb(0, iobase + 135); - return 1; - } - } - if(len >= 128) - { - for(i=0; i<64; i++) - { - b = inw(iobase + 136); - *addr++ = b; - *addr++ = b>>8; - } - len -= 128; - } - else - { - b = inw(iobase + 136); - *addr ++ = b; - len -= 1; - if(len) - *addr ++ = b>>8; - len -= 1; - } - } - outb(0, iobase + 135); - printk("first bytes = %02X %02X %02X %20X %02X %02X %02X\n",*start, start[1], start[2], start[3], start[4], start[5], start[6]); - return 1; -} -#endif -#undef STAT - -#define BOARD_NORMAL 0 -#define BOARD_NCR53C400 1 - -#include "../NCR5380.c" - -static struct scsi_host_template ecoscsi_template = { - .module = THIS_MODULE, - .name = "Serial Port EcoSCSI NCR5380", - .proc_name = "ecoscsi", - .info = ecoscsi_info, - .queuecommand = ecoscsi_queue_command, - .eh_abort_handler = NCR5380_abort, - .eh_bus_reset_handler = NCR5380_bus_reset, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING -}; - -static struct Scsi_Host *host; - -static int __init ecoscsi_init(void) -{ - - host = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata)); - if (!host) - return 0; - - host->io_port = 0x80ce8000; - host->n_io_port = 144; - host->irq = IRQ_NONE; - - if (!(request_region(host->io_port, host->n_io_port, "ecoscsi")) ) - goto unregister_scsi; - - ecoscsi_write(host, MODE_REG, 0x20); /* Is it really SCSI? */ - if (ecoscsi_read(host, MODE_REG) != 0x20) /* Write to a reg. */ - goto release_reg; - - ecoscsi_write(host, MODE_REG, 0x00 ); /* it back. */ - if (ecoscsi_read(host, MODE_REG) != 0x00) - goto release_reg; - - NCR5380_init(host, 0); - - printk("scsi%d: at port 0x%08lx irqs disabled", host->host_no, host->io_port); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - host->can_queue, host->cmd_per_lun, ECOSCSI_PUBLIC_RELEASE); - printk("\nscsi%d:", host->host_no); - NCR5380_print_options(host); - printk("\n"); - - scsi_add_host(host, NULL); /* XXX handle failure */ - scsi_scan_host(host); - return 0; - -release_reg: - release_region(host->io_port, host->n_io_port); -unregister_scsi: - scsi_host_put(host); - return -ENODEV; -} - -static void __exit ecoscsi_exit(void) -{ - scsi_remove_host(host); - - if (shpnt->irq != IRQ_NONE) - free_irq(shpnt->irq, NULL); - NCR5380_exit(host); - if (shpnt->io_port) - release_region(shpnt->io_port, shpnt->n_io_port); - - scsi_host_put(host); - return 0; -} - -module_init(ecoscsi_init); -module_exit(ecoscsi_exit); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("Econet-SCSI driver for Acorn machines"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index c21b8392c92..849cdf89f7b 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -23,15 +23,18 @@ #define OAKSCSI_PUBLIC_RELEASE 1 -#define NCR5380_read(reg) oakscsi_read(_instance, reg) -#define NCR5380_write(reg, value) oakscsi_write(_instance, reg, value) +#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) +#define NCR5380_local_declare() void __iomem *_base +#define NCR5380_setup(host) _base = priv(host)->base + +#define NCR5380_read(reg) readb(_base + ((reg) << 2)) +#define NCR5380_write(reg, value) writeb(value, _base + ((reg) << 2)) #define NCR5380_intr oakscsi_intr #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_proc_info oakscsi_proc_info -#define NCR5380_implementation_fields int port, ctrl -#define NCR5380_local_declare() struct Scsi_Host *_instance -#define NCR5380_setup(instance) _instance = instance +#define NCR5380_implementation_fields \ + void __iomem *base #define BOARD_NORMAL 0 #define BOARD_NCR53C400 1 @@ -39,60 +42,62 @@ #include "../NCR5380.h" #undef START_DMA_INITIATOR_RECEIVE_REG -#define START_DMA_INITIATOR_RECEIVE_REG (7 + 128) +#define START_DMA_INITIATOR_RECEIVE_REG (128 + 7) const char * oakscsi_info (struct Scsi_Host *spnt) { return ""; } -#define STAT(p) inw(p + 144) -extern void inswb(int from, void *to, int len); +#define STAT ((128 + 16) << 2) +#define DATA ((128 + 8) << 2) static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len) { - int iobase = instance->io_port; + void __iomem *base = priv(instance)->base; + printk("writing %p len %d\n",addr, len); if(!len) return -1; while(1) { int status; - while(((status = STAT(iobase)) & 0x100)==0); + while (((status = readw(base + STAT)) & 0x100)==0); } } static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, int len) { - int iobase = instance->io_port; + void __iomem *base = priv(instance)->base; printk("reading %p len %d\n", addr, len); while(len > 0) { - int status, timeout; + unsigned int status, timeout; unsigned long b; timeout = 0x01FFFFFF; - while(((status = STAT(iobase)) & 0x100)==0) + while (((status = readw(base + STAT)) & 0x100)==0) { timeout--; if(status & 0x200 || !timeout) { - printk("status = %08X\n",status); + printk("status = %08X\n", status); return 1; } } + if(len >= 128) { - inswb(iobase + 136, addr, 128); + readsw(base + DATA, addr, 128); addr += 128; len -= 128; } else { - b = (unsigned long) inw(iobase + 136); + b = (unsigned long) readw(base + DATA); *addr ++ = b; len -= 1; if(len) @@ -103,10 +108,8 @@ printk("reading %p len %d\n", addr, len); return 0; } -#define oakscsi_read(instance,reg) (inb((instance)->io_port + (reg))) -#define oakscsi_write(instance,reg,val) (outb((val), (instance)->io_port + (reg))) - #undef STAT +#undef DATA #include "../NCR5380.c" @@ -132,18 +135,26 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) struct Scsi_Host *host; int ret = -ENOMEM; - host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata)); - if (!host) + ret = ecard_request_resources(ec); + if (ret) goto out; - host->io_port = ecard_address(ec, ECARD_MEMC, 0); + host = scsi_host_alloc(&oakscsi_template, sizeof(struct NCR5380_hostdata)); + if (!host) { + ret = -ENOMEM; + goto release; + } + + priv(host)->base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), + ecard_resource_len(ec, ECARD_RES_MEMC)); + if (!priv(host)->base) { + ret = -ENOMEM; + goto unreg; + } + host->irq = IRQ_NONE; host->n_io_port = 255; - ret = -EBUSY; - if (!request_region (host->io_port, host->n_io_port, "Oak SCSI")) - goto unreg; - NCR5380_init(host, 0); printk("scsi%d: at port 0x%08lx irqs disabled", @@ -156,15 +167,17 @@ oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) ret = scsi_add_host(host, &ec->dev); if (ret) - goto out_release; + goto out_unmap; scsi_scan_host(host); goto out; - out_release: - release_region(host->io_port, host->n_io_port); + out_unmap: + iounmap(priv(host)->base); unreg: scsi_host_put(host); + release: + ecard_release_resources(ec); out: return ret; } @@ -177,8 +190,9 @@ static void __devexit oakscsi_remove(struct expansion_card *ec) scsi_remove_host(host); NCR5380_exit(host); - release_region(host->io_port, host->n_io_port); + iounmap(priv(host)->base); scsi_host_put(host); + ecard_release_resources(ec); } static const struct ecard_id oakscsi_cids[] = { diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c index 012cdea7946..cac35408673 100644 --- a/drivers/scsi/bvme6000_scsi.c +++ b/drivers/scsi/bvme6000_scsi.c @@ -74,6 +74,7 @@ bvme6000_probe(struct device *dev) goto out_put_host; } + dev_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -89,7 +90,7 @@ bvme6000_probe(struct device *dev) static __devexit int bvme6000_device_remove(struct device *dev) { - struct Scsi_Host *host = dev_to_shost(dev); + struct Scsi_Host *host = dev_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); scsi_remove_host(host); diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 2e2362d787c..502732ac270 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -173,20 +173,20 @@ static struct pci_device_id dptids[] = { }; MODULE_DEVICE_TABLE(pci,dptids); -static int adpt_detect(struct scsi_host_template* sht) +static void adpt_exit(void); + +static int adpt_detect(void) { struct pci_dev *pDev = NULL; adpt_hba* pHba; - adpt_init(); - PINFO("Detecting Adaptec I2O RAID controllers...\n"); /* search for all Adatpec I2O RAID cards */ while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) { if(pDev->device == PCI_DPT_DEVICE_ID || pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){ - if(adpt_install_hba(sht, pDev) ){ + if(adpt_install_hba(pDev) ){ PERROR("Could not Init an I2O RAID device\n"); PERROR("Will not try to detect others.\n"); return hba_count-1; @@ -248,34 +248,33 @@ rebuild_sys_tab: } for (pHba = hba_chain; pHba; pHba = pHba->next) { - if( adpt_scsi_register(pHba,sht) < 0){ + if (adpt_scsi_register(pHba) < 0) { adpt_i2o_delete_hba(pHba); continue; } pHba->initialized = TRUE; pHba->state &= ~DPTI_STATE_RESET; + scsi_scan_host(pHba->host); } // Register our control device node // nodes will need to be created in /dev to access this // the nodes can not be created from within the driver if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) { - adpt_i2o_sys_shutdown(); + adpt_exit(); return 0; } return hba_count; } -/* - * scsi_unregister will be called AFTER we return. - */ -static int adpt_release(struct Scsi_Host *host) +static int adpt_release(adpt_hba *pHba) { - adpt_hba* pHba = (adpt_hba*) host->hostdata[0]; + struct Scsi_Host *shost = pHba->host; + scsi_remove_host(shost); // adpt_i2o_quiesce_hba(pHba); adpt_i2o_delete_hba(pHba); - scsi_unregister(host); + scsi_host_put(shost); return 0; } @@ -882,7 +881,7 @@ static int adpt_reboot_event(struct notifier_block *n, ulong code, void *p) #endif -static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) +static int adpt_install_hba(struct pci_dev* pDev) { adpt_hba* pHba = NULL; @@ -1031,8 +1030,6 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) mutex_lock(&adpt_configuration_lock); - // scsi_unregister calls our adpt_release which - // does a quiese if(pHba->host){ free_irq(pHba->host->irq, pHba); } @@ -1084,17 +1081,6 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) } -static int adpt_init(void) -{ - printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); -#ifdef REBOOT_NOTIFIER - register_reboot_notifier(&adpt_reboot_notifier); -#endif - - return 0; -} - - static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun) { struct adpt_device* d; @@ -2180,37 +2166,6 @@ static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_d } -static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht) -{ - struct Scsi_Host *host = NULL; - - host = scsi_register(sht, sizeof(adpt_hba*)); - if (host == NULL) { - printk ("%s: scsi_register returned NULL\n",pHba->name); - return -1; - } - host->hostdata[0] = (unsigned long)pHba; - pHba->host = host; - - host->irq = pHba->pDev->irq; - /* no IO ports, so don't have to set host->io_port and - * host->n_io_port - */ - host->io_port = 0; - host->n_io_port = 0; - /* see comments in scsi_host.h */ - host->max_id = 16; - host->max_lun = 256; - host->max_channel = pHba->top_scsi_channel + 1; - host->cmd_per_lun = 1; - host->unique_id = (uint) pHba; - host->sg_tablesize = pHba->sg_tablesize; - host->can_queue = pHba->post_fifo_size; - - return 0; -} - - static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) { adpt_hba* pHba; @@ -3329,12 +3284,10 @@ static static void adpt_delay(int millisec) #endif -static struct scsi_host_template driver_template = { +static struct scsi_host_template adpt_template = { .name = "dpt_i2o", .proc_name = "dpt_i2o", .proc_info = adpt_proc_info, - .detect = adpt_detect, - .release = adpt_release, .info = adpt_info, .queuecommand = adpt_queue, .eh_abort_handler = adpt_abort, @@ -3348,5 +3301,62 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, }; -#include "scsi_module.c" + +static s32 adpt_scsi_register(adpt_hba* pHba) +{ + struct Scsi_Host *host; + + host = scsi_host_alloc(&adpt_template, sizeof(adpt_hba*)); + if (host == NULL) { + printk ("%s: scsi_host_alloc returned NULL\n",pHba->name); + return -1; + } + host->hostdata[0] = (unsigned long)pHba; + pHba->host = host; + + host->irq = pHba->pDev->irq; + /* no IO ports, so don't have to set host->io_port and + * host->n_io_port + */ + host->io_port = 0; + host->n_io_port = 0; + /* see comments in scsi_host.h */ + host->max_id = 16; + host->max_lun = 256; + host->max_channel = pHba->top_scsi_channel + 1; + host->cmd_per_lun = 1; + host->unique_id = (uint) pHba; + host->sg_tablesize = pHba->sg_tablesize; + host->can_queue = pHba->post_fifo_size; + + if (scsi_add_host(host, &pHba->pDev->dev)) { + scsi_host_put(host); + return -1; + } + + return 0; +} + +static int __init adpt_init(void) +{ + int count; + + printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); +#ifdef REBOOT_NOTIFIER + register_reboot_notifier(&adpt_reboot_notifier); +#endif + + count = adpt_detect(); + + return count > 0 ? 0 : -ENODEV; +} + +static void __exit adpt_exit(void) +{ + while (hba_chain) + adpt_release(hba_chain); +} + +module_init(adpt_init); +module_exit(adpt_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index fd79068c586..0892f6c7031 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -28,11 +28,9 @@ * SCSI interface function Prototypes */ -static int adpt_detect(struct scsi_host_template * sht); static int adpt_queue(struct scsi_cmnd * cmd, void (*cmdcomplete) (struct scsi_cmnd *)); static int adpt_abort(struct scsi_cmnd * cmd); static int adpt_reset(struct scsi_cmnd* cmd); -static int adpt_release(struct Scsi_Host *host); static int adpt_slave_configure(struct scsi_device *); static const char *adpt_info(struct Scsi_Host *pSHost); @@ -49,8 +47,6 @@ static int adpt_device_reset(struct scsi_cmnd* cmd); #define DPT_DRIVER_NAME "Adaptec I2O RAID" -#ifndef HOSTS_C - #include "dpt/sys_info.h" #include <linux/wait.h> #include "dpt/dpti_i2o.h" @@ -289,7 +285,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba); static s32 adpt_i2o_hrt_get(adpt_hba* pHba); static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice); static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd); -static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht); +static s32 adpt_scsi_register(adpt_hba* pHba); static s32 adpt_hba_reset(adpt_hba* pHba); static s32 adpt_i2o_reset_hba(adpt_hba* pHba); static s32 adpt_rescan(adpt_hba* pHba); @@ -299,7 +295,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba); static void adpt_inquiry(adpt_hba* pHba); static void adpt_fail_posted_scbs(adpt_hba* pHba); static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun); -static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ; +static int adpt_install_hba(struct pci_dev* pDev) ; static int adpt_i2o_online_hba(adpt_hba* pHba); static void adpt_i2o_post_wait_complete(u32, int); static int adpt_i2o_systab_send(adpt_hba* pHba); @@ -343,5 +339,4 @@ static void adpt_i386_info(sysInfo_S* si); #define FW_DEBUG_BLED_OFFSET 8 #define FW_DEBUG_FLAGS_NO_HEADERS_B 0x01 -#endif /* !HOSTS_C */ #endif /* _DPT_H */ diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index 77b06a983fa..95cf7b6cd62 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -2314,6 +2314,7 @@ int __devinit scsi_esp_register(struct esp *esp, struct device *dev) esp->host->transportt = esp_transport_template; esp->host->max_lun = ESP_MAX_LUN; esp->host->cmd_per_lun = 2; + esp->host->unique_id = instance; esp_set_clock_params(esp); @@ -2337,7 +2338,7 @@ int __devinit scsi_esp_register(struct esp *esp, struct device *dev) if (err) return err; - esp->host->unique_id = instance++; + instance++; scsi_scan_host(esp->host); diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index d0b95ce0ba0..55e4d2dc2bb 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -902,11 +902,6 @@ static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, return; /* GDT PCI controller found, resources are already in pdev */ pcistr[*cnt].pdev = pdev; - pcistr[*cnt].vendor_id = vendor; - pcistr[*cnt].device_id = device; - pcistr[*cnt].subdevice_id = pdev->subsystem_device; - pcistr[*cnt].bus = pdev->bus->number; - pcistr[*cnt].device_fn = pdev->devfn; pcistr[*cnt].irq = pdev->irq; base0 = pci_resource_flags(pdev, 0); base1 = pci_resource_flags(pdev, 1); @@ -926,7 +921,8 @@ static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, pcistr[*cnt].io = pci_resource_start(pdev, 1); } TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n", - pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), + pcistr[*cnt].pdev->bus->number, + PCI_SLOT(pcistr[*cnt].pdev->devfn), pcistr[*cnt].irq, pcistr[*cnt].dpmem)); (*cnt)++; } @@ -946,20 +942,20 @@ static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt) changed = FALSE; for (i = 0; i < cnt-1; ++i) { if (!reverse_scan) { - if ((pcistr[i].bus > pcistr[i+1].bus) || - (pcistr[i].bus == pcistr[i+1].bus && - PCI_SLOT(pcistr[i].device_fn) > - PCI_SLOT(pcistr[i+1].device_fn))) { + if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) || + (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number && + PCI_SLOT(pcistr[i].pdev->devfn) > + PCI_SLOT(pcistr[i+1].pdev->devfn))) { temp = pcistr[i]; pcistr[i] = pcistr[i+1]; pcistr[i+1] = temp; changed = TRUE; } } else { - if ((pcistr[i].bus < pcistr[i+1].bus) || - (pcistr[i].bus == pcistr[i+1].bus && - PCI_SLOT(pcistr[i].device_fn) < - PCI_SLOT(pcistr[i+1].device_fn))) { + if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) || + (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number && + PCI_SLOT(pcistr[i].pdev->devfn) < + PCI_SLOT(pcistr[i+1].pdev->devfn))) { temp = pcistr[i]; pcistr[i] = pcistr[i+1]; pcistr[i+1] = temp; @@ -1176,17 +1172,16 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) TRACE(("gdth_init_pci()\n")); - if (pcistr->vendor_id == PCI_VENDOR_ID_INTEL) + if (pcistr->pdev->vendor == PCI_VENDOR_ID_INTEL) ha->oem_id = OEM_ID_INTEL; else ha->oem_id = OEM_ID_ICP; - ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8); - ha->stype = (ulong32)pcistr->device_id; - ha->subdevice_id = pcistr->subdevice_id; + ha->brd_phys = (pcistr->pdev->bus->number << 8) | (pcistr->pdev->devfn & 0xf8); + ha->stype = (ulong32)pcistr->pdev->device; ha->irq = pcistr->irq; ha->pdev = pcistr->pdev; - if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ + if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6_dpram_str)); if (ha->brd == NULL) { @@ -1293,7 +1288,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) ha->dma64_support = 0; - } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */ + } else if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */ ha->plx = (gdt6c_plx_regs *)pcistr->io; TRACE2(("init_pci_new() dpmem %lx irq %d\n", pcistr->dpmem,ha->irq)); @@ -4601,7 +4596,8 @@ static int __init gdth_detect(Scsi_Host_Template *shtp) } /* controller found and initialized */ printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", - pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); + pcistr[ctr].pdev->bus->number, + PCI_SLOT(pcistr[ctr].pdev->devfn), ha->irq); if (request_irq(ha->irq, gdth_interrupt, IRQF_DISABLED|IRQF_SHARED, "gdth", ha)) @@ -4637,7 +4633,7 @@ static int __init gdth_detect(Scsi_Host_Template *shtp) #endif ha->scratch_busy = FALSE; ha->req_first = NULL; - ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES; + ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES; if (max_ids > 0 && max_ids < ha->tid_cnt) ha->tid_cnt = max_ids; for (i=0; i<GDTH_MAXCMDS; ++i) @@ -4810,7 +4806,7 @@ static const char *gdth_ctr_name(int hanum) } else if (ha->type == GDT_ISA) { return("GDT2000/2020"); } else if (ha->type == GDT_PCI) { - switch (ha->stype) { + switch (ha->pdev->device) { case PCI_DEVICE_ID_VORTEX_GDT60x0: return("GDT6000/6020/6050"); case PCI_DEVICE_ID_VORTEX_GDT6000B: @@ -5448,12 +5444,12 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, ctrt.type = (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe); if (ha->stype >= 0x300) - ctrt.ext_type = 0x6000 | ha->subdevice_id; + ctrt.ext_type = 0x6000 | ha->pdev->subsystem_device; else ctrt.ext_type = 0x6000 | ha->stype; } - ctrt.device_id = ha->stype; - ctrt.sub_device_id = ha->subdevice_id; + ctrt.device_id = ha->pdev->device; + ctrt.sub_device_id = ha->pdev->subsystem_device; } ctrt.info = ha->brd_phys; ctrt.oem_id = ha->oem_id; diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index 8c29eafd51c..37423300592 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -845,11 +845,6 @@ typedef struct { /* PCI resources */ typedef struct { struct pci_dev *pdev; - ushort vendor_id; /* vendor (ICP, Intel, ..) */ - ushort device_id; /* device ID (0,..,9) */ - ushort subdevice_id; /* sub device ID */ - unchar bus; /* PCI bus */ - unchar device_fn; /* PCI device/function no. */ ulong dpmem; /* DPRAM address */ ulong io; /* IO address */ ulong io_mm; /* IO address mem. mapped */ @@ -862,7 +857,6 @@ typedef struct { ushort oem_id; /* OEM */ ushort type; /* controller class */ ulong32 stype; /* subtype (PCI: device ID) */ - ushort subdevice_id; /* sub device ID (PCI) */ ushort fw_vers; /* firmware version */ ushort cache_feat; /* feat. cache serv. (s/g,..)*/ ushort raw_feat; /* feat. raw service (s/g,..)*/ diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index bd8e7f323c6..96bc31266c9 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -220,7 +220,7 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) get_device(&shost->shost_gendev); if (shost->transportt->host_size && - (shost->shost_data = kmalloc(shost->transportt->host_size, + (shost->shost_data = kzalloc(shost->transportt->host_size, GFP_KERNEL)) == NULL) goto out_del_classdev; diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 5870866abc9..5ecc63d1b43 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -393,12 +393,6 @@ static int map_sg_data(struct scsi_cmnd *cmd, return 1; else if (sg_mapped < 0) return 0; - else if (sg_mapped > SG_ALL) { - printk(KERN_ERR - "ibmvscsi: More than %d mapped sg entries, got %d\n", - SG_ALL, sg_mapped); - return 0; - } set_srp_direction(cmd, srp_cmd, sg_mapped); @@ -708,8 +702,7 @@ static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd, struct srp_cmd *srp_cmd; struct srp_event_struct *evt_struct; struct srp_indirect_buf *indirect; - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)&cmnd->device->host->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(cmnd->device->host); u16 lun = lun_from_dev(cmnd->device); u8 out_fmt, in_fmt; @@ -960,8 +953,7 @@ static void sync_completion(struct srp_event_struct *evt_struct) */ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) { - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)cmd->device->host->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); struct srp_tsk_mgmt *tsk_mgmt; struct srp_event_struct *evt; struct srp_event_struct *tmp_evt, *found_evt; @@ -1084,9 +1076,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) */ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) { - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)cmd->device->host->hostdata; - + struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); struct srp_tsk_mgmt *tsk_mgmt; struct srp_event_struct *evt; struct srp_event_struct *tmp_evt, *pos; @@ -1183,8 +1173,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) static int ibmvscsi_eh_host_reset_handler(struct scsi_cmnd *cmd) { unsigned long wait_switch = 0; - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)cmd->device->host->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(cmd->device->host); dev_err(hostdata->dev, "Resetting connection due to error recovery\n"); @@ -1412,8 +1401,7 @@ static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth) static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%s\n", @@ -1433,8 +1421,7 @@ static ssize_t show_host_partition_name(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%s\n", @@ -1454,8 +1441,7 @@ static ssize_t show_host_partition_number(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%d\n", @@ -1474,8 +1460,7 @@ static struct class_device_attribute ibmvscsi_host_partition_number = { static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%d\n", @@ -1494,8 +1479,7 @@ static struct class_device_attribute ibmvscsi_host_mad_version = { static ssize_t show_host_os_type(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); int len; len = snprintf(buf, PAGE_SIZE, "%d\n", hostdata->madapter_info.os_type); @@ -1513,8 +1497,7 @@ static struct class_device_attribute ibmvscsi_host_os_type = { static ssize_t show_host_config(struct class_device *class_dev, char *buf) { struct Scsi_Host *shost = class_to_shost(class_dev); - struct ibmvscsi_host_data *hostdata = - (struct ibmvscsi_host_data *)shost->hostdata; + struct ibmvscsi_host_data *hostdata = shost_priv(shost); /* returns null-terminated host config data */ if (ibmvscsi_do_host_config(hostdata, buf, PAGE_SIZE) == 0) @@ -1582,7 +1565,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) goto scsi_host_alloc_failed; } - hostdata = (struct ibmvscsi_host_data *)host->hostdata; + hostdata = shost_priv(host); memset(hostdata, 0x00, sizeof(*hostdata)); INIT_LIST_HEAD(&hostdata->sent); hostdata->host = host; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index bb90df8bdce..1cc01acc280 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -328,17 +328,15 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co u8 *buf; /* stuff a sense request in front of our current request */ - pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC); - rq = kmalloc (sizeof (struct request), GFP_ATOMIC); - buf = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC); - if (pc == NULL || rq == NULL || buf == NULL) { + pc = kzalloc(sizeof(idescsi_pc_t), GFP_ATOMIC); + rq = kmalloc(sizeof(struct request), GFP_ATOMIC); + buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC); + if (!pc || !rq || !buf) { kfree(buf); kfree(rq); kfree(pc); return -ENOMEM; } - memset (pc, 0, sizeof (idescsi_pc_t)); - memset (buf, 0, SCSI_SENSE_BUFFERSIZE); ide_init_drive_cmd(rq); rq->special = (char *) pc; pc->rq = rq; diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 0464c182c57..005d2b05f32 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -1159,11 +1159,10 @@ static int __imm_attach(struct parport *pb) init_waitqueue_head(&waiting); - dev = kmalloc(sizeof(imm_struct), GFP_KERNEL); + dev = kzalloc(sizeof(imm_struct), GFP_KERNEL); if (!dev) return -ENOMEM; - memset(dev, 0, sizeof(imm_struct)); dev->base = -1; dev->mode = IMM_AUTODETECT; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index f142eafb6fc..b41dfb53902 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3829,18 +3829,18 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg, /** * ipr_sata_reset - Reset the SATA port - * @ap: SATA port to reset + * @link: SATA link to reset * @classes: class of the attached device * - * This function issues a SATA phy reset to the affected ATA port. + * This function issues a SATA phy reset to the affected ATA link. * * Return value: * 0 on success / non-zero on failure **/ -static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes, +static int ipr_sata_reset(struct ata_link *link, unsigned int *classes, unsigned long deadline) { - struct ipr_sata_port *sata_port = ap->private_data; + struct ipr_sata_port *sata_port = link->ap->private_data; struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg; struct ipr_resource_entry *res; unsigned long lock_flags = 0; @@ -4981,22 +4981,22 @@ static void ipr_ata_phy_reset(struct ata_port *ap) rc = ipr_device_reset(ioa_cfg, res); if (rc) { - ap->ops->port_disable(ap); + ata_port_disable(ap); goto out_unlock; } switch(res->cfgte.proto) { case IPR_PROTO_SATA: case IPR_PROTO_SAS_STP: - ap->device[0].class = ATA_DEV_ATA; + ap->link.device[0].class = ATA_DEV_ATA; break; case IPR_PROTO_SATA_ATAPI: case IPR_PROTO_SAS_STP_ATAPI: - ap->device[0].class = ATA_DEV_ATAPI; + ap->link.device[0].class = ATA_DEV_ATAPI; break; default: - ap->device[0].class = ATA_DEV_UNKNOWN; - ap->ops->port_disable(ap); + ap->link.device[0].class = ATA_DEV_UNKNOWN; + ata_port_disable(ap); break; }; @@ -5262,7 +5262,6 @@ static u8 ipr_ata_check_altstatus(struct ata_port *ap) } static struct ata_port_operations ipr_sata_ops = { - .port_disable = ata_port_disable, .check_status = ipr_ata_check_status, .check_altstatus = ipr_ata_check_altstatus, .dev_select = ata_noop_dev_select, diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 9f8ed6b8157..492a51bd6aa 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -7068,14 +7068,13 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr) subdevice_id = pci_dev->subsystem_device; /* found a controller */ - ha = kmalloc(sizeof (ips_ha_t), GFP_KERNEL); + ha = kzalloc(sizeof (ips_ha_t), GFP_KERNEL); if (ha == NULL) { IPS_PRINTK(KERN_WARNING, pci_dev, "Unable to allocate temporary ha struct\n"); return -1; } - memset(ha, 0, sizeof (ips_ha_t)); ips_sh[index] = NULL; ips_ha[index] = ha; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index aebcd5fcdc5..a21455d0274 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1885,7 +1885,7 @@ static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock, struct sockaddr_in *sin; int rc = 0, len; - addr = kmalloc(GFP_KERNEL, sizeof(*addr)); + addr = kmalloc(sizeof(*addr), GFP_KERNEL); if (!addr) return -ENOMEM; @@ -2216,11 +2216,13 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) static int iscsi_tcp_slave_configure(struct scsi_device *sdev) { + blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY); blk_queue_dma_alignment(sdev->request_queue, 0); return 0; } static struct scsi_host_template iscsi_sht = { + .module = THIS_MODULE, .name = "iSCSI Initiator over TCP/IP", .queuecommand = iscsi_queuecommand, .change_queue_depth = iscsi_change_queue_depth, diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 5c32a69e41b..3126824da36 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -101,13 +101,12 @@ lasi700_probe(struct parisc_device *dev) struct NCR_700_Host_Parameters *hostdata; struct Scsi_Host *host; - hostdata = kmalloc(sizeof(*hostdata), GFP_KERNEL); + hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); if (!hostdata) { printk(KERN_ERR "%s: Failed to allocate host data\n", dev->dev.bus_id); return -ENOMEM; } - memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); hostdata->dev = &dev->dev; dma_set_mask(&dev->dev, DMA_32BIT_MASK); diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 4d85ce10019..efceed451b4 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -596,9 +596,16 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn, nop->cmdsn = cpu_to_be32(session->cmdsn); if (hdr->itt != RESERVED_ITT) { hdr->itt = build_itt(mtask->itt, conn->id, session->age); + /* + * TODO: We always use immediate, so we never hit this. + * If we start to send tmfs or nops as non-immediate then + * we should start checking the cmdsn numbers for mgmt tasks. + */ if (conn->c_stage == ISCSI_CONN_STARTED && - !(hdr->opcode & ISCSI_OP_IMMEDIATE)) + !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { + session->queued_cmdsn++; session->cmdsn++; + } } if (session->tt->init_mgmt_task) @@ -641,9 +648,11 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) /* * Check for iSCSI window and take care of CmdSN wrap-around */ - if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) { - debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n", - session->max_cmdsn, session->cmdsn); + if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) { + debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u " + "CmdSN %u/%u\n", session->exp_cmdsn, + session->max_cmdsn, session->cmdsn, + session->queued_cmdsn); return -ENOSPC; } return 0; @@ -722,23 +731,25 @@ check_mgmt: /* process command queue */ while (!list_empty(&conn->xmitqueue)) { - rc = iscsi_check_cmdsn_window_closed(conn); - if (rc) { - spin_unlock_bh(&conn->session->lock); - return rc; - } /* * iscsi tcp may readd the task to the xmitqueue to send * write data */ conn->ctask = list_entry(conn->xmitqueue.next, struct iscsi_cmd_task, running); - if (conn->ctask->state == ISCSI_TASK_PENDING) { + switch (conn->ctask->state) { + case ISCSI_TASK_ABORTING: + break; + case ISCSI_TASK_PENDING: iscsi_prep_scsi_cmd_pdu(conn->ctask); conn->session->tt->init_cmd_task(conn->ctask); + /* fall through */ + default: + conn->ctask->state = ISCSI_TASK_RUNNING; + break; } - conn->ctask->state = ISCSI_TASK_RUNNING; list_move_tail(conn->xmitqueue.next, &conn->run_list); + rc = iscsi_xmit_ctask(conn); if (rc) goto again; @@ -834,12 +845,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) goto fault; } - /* - * We check this here and in data xmit, because if we get to the point - * that this check is hitting the window then we have enough IO in - * flight and enough IO waiting to be transmitted it is better - * to let the scsi/block layer queue up. - */ if (iscsi_check_cmdsn_window_closed(conn)) { reason = FAILURE_WINDOW_CLOSED; goto reject; @@ -850,6 +855,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) reason = FAILURE_OOM; goto reject; } + session->queued_cmdsn++; + sc->SCp.phase = session->age; sc->SCp.ptr = (char *)ctask; @@ -1049,7 +1056,9 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, ctask->mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); if (!ctask->mtask) { + spin_unlock_bh(&session->lock); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + spin_lock_bh(&session->lock) debug_scsi("abort sent failure [itt 0x%x]\n", ctask->itt); return -EPERM; } @@ -1066,6 +1075,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt); } spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); scsi_queue_work(session->host, &conn->xmitwork); /* @@ -1083,6 +1093,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, if (signal_pending(current)) flush_signals(current); del_timer_sync(&conn->tmabort_timer); + mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); return 0; } @@ -1140,7 +1151,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, if (!sc) return; - if (ctask->state != ISCSI_TASK_PENDING) + if (ctask->state == ISCSI_TASK_PENDING) + /* + * cmd never made it to the xmit thread, so we should not count + * the cmd in the sequencing + */ + conn->session->queued_cmdsn--; + else conn->session->tt->cleanup_cmd_task(conn, ctask); iscsi_ctask_mtask_cleanup(ctask); @@ -1152,31 +1169,45 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, __iscsi_put_ctask(ctask); } +static void iscsi_suspend_tx(struct iscsi_conn *conn) +{ + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + scsi_flush_work(conn->session->host); +} + +static void iscsi_start_tx(struct iscsi_conn *conn) +{ + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + scsi_queue_work(conn->session->host, &conn->xmitwork); +} + int iscsi_eh_abort(struct scsi_cmnd *sc) { + struct Scsi_Host *host = sc->device->host; + struct iscsi_session *session = iscsi_hostdata(host->hostdata); struct iscsi_cmd_task *ctask; struct iscsi_conn *conn; - struct iscsi_session *session; int rc; + mutex_lock(&session->eh_mutex); + spin_lock_bh(&session->lock); /* * if session was ISCSI_STATE_IN_RECOVERY then we may not have * got the command. */ if (!sc->SCp.ptr) { debug_scsi("sc never reached iscsi layer or it completed.\n"); + spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); return SUCCESS; } ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; conn = ctask->conn; - session = conn->session; conn->eh_abort_cnt++; debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); - spin_lock_bh(&session->lock); - /* * If we are not logged in or we have started a new session * then let the host reset code handle this @@ -1213,6 +1244,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) switch (conn->tmabort_state) { case TMABORT_SUCCESS: spin_unlock_bh(&session->lock); + iscsi_suspend_tx(conn); /* * clean up task if aborted. grab the recv lock as a writer */ @@ -1221,11 +1253,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) fail_command(conn, ctask, DID_ABORT << 16); spin_unlock(&session->lock); write_unlock_bh(conn->recv_lock); - /* - * make sure xmit thread is not still touching the - * ctask/scsi_cmnd - */ - scsi_flush_work(session->host); + iscsi_start_tx(conn); goto success_unlocked; case TMABORT_NOT_FOUND: if (!ctask->sc) { @@ -1245,12 +1273,14 @@ success: spin_unlock_bh(&session->lock); success_unlocked: debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + mutex_unlock(&session->eh_mutex); return SUCCESS; failed: spin_unlock_bh(&session->lock); failed_unlocked: debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); + mutex_unlock(&session->eh_mutex); return FAILED; } EXPORT_SYMBOL_GPL(iscsi_eh_abort); @@ -1392,11 +1422,12 @@ iscsi_session_setup(struct iscsi_transport *iscsit, session->state = ISCSI_STATE_FREE; session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; session->cmds_max = cmds_max; - session->cmdsn = initial_cmdsn; + session->queued_cmdsn = session->cmdsn = initial_cmdsn; session->exp_cmdsn = initial_cmdsn + 1; session->max_cmdsn = initial_cmdsn + 1; session->max_r2t = 1; session->tt = iscsit; + mutex_init(&session->eh_mutex); /* initialize SCSI PDU commands pool */ if (iscsi_pool_init(&session->cmdpool, session->cmds_max, @@ -1473,6 +1504,7 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) struct iscsi_session *session = iscsi_hostdata(shost->hostdata); struct module *owner = cls_session->transport->owner; + iscsi_unblock_session(cls_session); scsi_remove_host(shost); iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); @@ -1615,11 +1647,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) kfree(conn->persistent_address); __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, sizeof(void*)); - if (session->leadconn == conn) { + if (session->leadconn == conn) session->leadconn = NULL; - /* no connections exits.. reset sequencing */ - session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; - } spin_unlock_bh(&session->lock); kfifo_free(conn->mgmtqueue); @@ -1649,6 +1678,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) spin_lock_bh(&session->lock); conn->c_stage = ISCSI_CONN_STARTED; session->state = ISCSI_STATE_LOGGED_IN; + session->queued_cmdsn = session->cmdsn; switch(conn->stop_stage) { case STOP_CONN_RECOVER: @@ -1731,9 +1761,22 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, { int old_stop_stage; + mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); if (conn->stop_stage == STOP_CONN_TERM) { spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); + return; + } + + /* + * The LLD either freed/unset the lock on us, or userspace called + * stop but did not create a proper connection (connection was never + * bound or it was unbound then stop was called). + */ + if (!conn->recv_lock) { + spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); return; } @@ -1750,9 +1793,9 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, old_stop_stage = conn->stop_stage; conn->stop_stage = flag; conn->c_stage = ISCSI_CONN_STOPPED; - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); spin_unlock_bh(&session->lock); - scsi_flush_work(session->host); + + iscsi_suspend_tx(conn); write_lock_bh(conn->recv_lock); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); @@ -1781,6 +1824,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, fail_all_commands(conn); flush_control_queues(session, conn); spin_unlock_bh(&session->lock); + mutex_unlock(&session->eh_mutex); } void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig index aafdc92f831..c01a40d321d 100644 --- a/drivers/scsi/libsas/Kconfig +++ b/drivers/scsi/libsas/Kconfig @@ -30,6 +30,14 @@ config SCSI_SAS_LIBSAS This provides transport specific helpers for SAS drivers which use the domain device construct (like the aic94xxx). +config SCSI_SAS_ATA + bool "ATA support for libsas (requires libata)" + depends on SCSI_SAS_LIBSAS + depends on ATA = y || ATA = SCSI_SAS_LIBSAS + help + Builds in ATA support into libsas. Will necessitate + the loading of libata along with libsas. + config SCSI_SAS_LIBSAS_DEBUG bool "Compile the SAS Domain Transport Attributes in debug mode" default y diff --git a/drivers/scsi/libsas/Makefile b/drivers/scsi/libsas/Makefile index 44d972a3b4b..fd387b91856 100644 --- a/drivers/scsi/libsas/Makefile +++ b/drivers/scsi/libsas/Makefile @@ -34,3 +34,4 @@ libsas-y += sas_init.o \ sas_discover.o \ sas_expander.o \ sas_scsi_host.o +libsas-$(CONFIG_SCSI_SAS_ATA) += sas_ata.o diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c new file mode 100644 index 00000000000..0829b55c64d --- /dev/null +++ b/drivers/scsi/libsas/sas_ata.c @@ -0,0 +1,816 @@ +/* + * Support for SATA devices on Serial Attached SCSI (SAS) controllers + * + * Copyright (C) 2006 IBM Corporation + * + * Written by: Darrick J. Wong <djwong@us.ibm.com>, IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include <linux/scatterlist.h> + +#include <scsi/sas_ata.h> +#include "sas_internal.h" +#include <scsi/scsi_host.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_tcq.h> +#include <scsi/scsi.h> +#include <scsi/scsi_transport.h> +#include <scsi/scsi_transport_sas.h> +#include "../scsi_sas_internal.h" +#include "../scsi_transport_api.h" +#include <scsi/scsi_eh.h> + +static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts) +{ + /* Cheesy attempt to translate SAS errors into ATA. Hah! */ + + /* transport error */ + if (ts->resp == SAS_TASK_UNDELIVERED) + return AC_ERR_ATA_BUS; + + /* ts->resp == SAS_TASK_COMPLETE */ + /* task delivered, what happened afterwards? */ + switch (ts->stat) { + case SAS_DEV_NO_RESPONSE: + return AC_ERR_TIMEOUT; + + case SAS_INTERRUPTED: + case SAS_PHY_DOWN: + case SAS_NAK_R_ERR: + return AC_ERR_ATA_BUS; + + + case SAS_DATA_UNDERRUN: + /* + * Some programs that use the taskfile interface + * (smartctl in particular) can cause underrun + * problems. Ignore these errors, perhaps at our + * peril. + */ + return 0; + + case SAS_DATA_OVERRUN: + case SAS_QUEUE_FULL: + case SAS_DEVICE_UNKNOWN: + case SAS_SG_ERR: + return AC_ERR_INVALID; + + case SAM_CHECK_COND: + case SAS_OPEN_TO: + case SAS_OPEN_REJECT: + SAS_DPRINTK("%s: Saw error %d. What to do?\n", + __FUNCTION__, ts->stat); + return AC_ERR_OTHER; + + case SAS_ABORTED_TASK: + return AC_ERR_DEV; + + case SAS_PROTO_RESPONSE: + /* This means the ending_fis has the error + * value; return 0 here to collect it */ + return 0; + default: + return 0; + } +} + +static void sas_ata_task_done(struct sas_task *task) +{ + struct ata_queued_cmd *qc = task->uldd_task; + struct domain_device *dev; + struct task_status_struct *stat = &task->task_status; + struct ata_task_resp *resp = (struct ata_task_resp *)stat->buf; + struct sas_ha_struct *sas_ha; + enum ata_completion_errors ac; + unsigned long flags; + + if (!qc) + goto qc_already_gone; + + dev = qc->ap->private_data; + sas_ha = dev->port->ha; + + spin_lock_irqsave(dev->sata_dev.ap->lock, flags); + if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_GOOD) { + ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); + qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); + dev->sata_dev.sstatus = resp->sstatus; + dev->sata_dev.serror = resp->serror; + dev->sata_dev.scontrol = resp->scontrol; + } else if (stat->stat != SAM_STAT_GOOD) { + ac = sas_to_ata_err(stat); + if (ac) { + SAS_DPRINTK("%s: SAS error %x\n", __FUNCTION__, + stat->stat); + /* We saw a SAS error. Send a vague error. */ + qc->err_mask = ac; + dev->sata_dev.tf.feature = 0x04; /* status err */ + dev->sata_dev.tf.command = ATA_ERR; + } + } + + qc->lldd_task = NULL; + if (qc->scsicmd) + ASSIGN_SAS_TASK(qc->scsicmd, NULL); + ata_qc_complete(qc); + spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags); + + /* + * If the sas_task has an ata qc, a scsi_cmnd and the aborted + * flag is set, then we must have come in via the libsas EH + * functions. When we exit this function, we need to put the + * scsi_cmnd on the list of finished errors. The ata_qc_complete + * call cleans up the libata side of things but we're protected + * from the scsi_cmnd going away because the scsi_cmnd is owned + * by the EH, making libata's call to scsi_done a NOP. + */ + spin_lock_irqsave(&task->task_state_lock, flags); + if (qc->scsicmd && task->task_state_flags & SAS_TASK_STATE_ABORTED) + scsi_eh_finish_cmd(qc->scsicmd, &sas_ha->eh_done_q); + spin_unlock_irqrestore(&task->task_state_lock, flags); + +qc_already_gone: + list_del_init(&task->list); + sas_free_task(task); +} + +static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) +{ + int res; + struct sas_task *task; + struct domain_device *dev = qc->ap->private_data; + struct sas_ha_struct *sas_ha = dev->port->ha; + struct Scsi_Host *host = sas_ha->core.shost; + struct sas_internal *i = to_sas_internal(host->transportt); + struct scatterlist *sg; + unsigned int num = 0; + unsigned int xfer = 0; + + task = sas_alloc_task(GFP_ATOMIC); + if (!task) + return AC_ERR_SYSTEM; + task->dev = dev; + task->task_proto = SAS_PROTOCOL_STP; + task->task_done = sas_ata_task_done; + + if (qc->tf.command == ATA_CMD_FPDMA_WRITE || + qc->tf.command == ATA_CMD_FPDMA_READ) { + /* Need to zero out the tag libata assigned us */ + qc->tf.nsect = 0; + } + + ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); + task->uldd_task = qc; + if (is_atapi_taskfile(&qc->tf)) { + memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); + task->total_xfer_len = qc->nbytes + qc->pad_len; + task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem; + } else { + ata_for_each_sg(sg, qc) { + num++; + xfer += sg->length; + } + + task->total_xfer_len = xfer; + task->num_scatter = num; + } + + task->data_dir = qc->dma_dir; + task->scatter = qc->__sg; + task->ata_task.retry_count = 1; + task->task_state_flags = SAS_TASK_STATE_PENDING; + qc->lldd_task = task; + + switch (qc->tf.protocol) { + case ATA_PROT_NCQ: + task->ata_task.use_ncq = 1; + /* fall through */ + case ATA_PROT_ATAPI_DMA: + case ATA_PROT_DMA: + task->ata_task.dma_xfer = 1; + break; + } + + if (qc->scsicmd) + ASSIGN_SAS_TASK(qc->scsicmd, task); + + if (sas_ha->lldd_max_execute_num < 2) + res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC); + else + res = sas_queue_up(task); + + /* Examine */ + if (res) { + SAS_DPRINTK("lldd_execute_task returned: %d\n", res); + + if (qc->scsicmd) + ASSIGN_SAS_TASK(qc->scsicmd, NULL); + sas_free_task(task); + return AC_ERR_SYSTEM; + } + + return 0; +} + +static u8 sas_ata_check_status(struct ata_port *ap) +{ + struct domain_device *dev = ap->private_data; + return dev->sata_dev.tf.command; +} + +static void sas_ata_phy_reset(struct ata_port *ap) +{ + struct domain_device *dev = ap->private_data; + struct sas_internal *i = + to_sas_internal(dev->port->ha->core.shost->transportt); + int res = 0; + + if (i->dft->lldd_I_T_nexus_reset) + res = i->dft->lldd_I_T_nexus_reset(dev); + + if (res) + SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__); + + switch (dev->sata_dev.command_set) { + case ATA_COMMAND_SET: + SAS_DPRINTK("%s: Found ATA device.\n", __FUNCTION__); + ap->link.device[0].class = ATA_DEV_ATA; + break; + case ATAPI_COMMAND_SET: + SAS_DPRINTK("%s: Found ATAPI device.\n", __FUNCTION__); + ap->link.device[0].class = ATA_DEV_ATAPI; + break; + default: + SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", + __FUNCTION__, + dev->sata_dev.command_set); + ap->link.device[0].class = ATA_DEV_UNKNOWN; + break; + } + + ap->cbl = ATA_CBL_SATA; +} + +static void sas_ata_post_internal(struct ata_queued_cmd *qc) +{ + if (qc->flags & ATA_QCFLAG_FAILED) + qc->err_mask |= AC_ERR_OTHER; + + if (qc->err_mask) { + /* + * Find the sas_task and kill it. By this point, + * libata has decided to kill the qc, so we needn't + * bother with sas_ata_task_done. But we still + * ought to abort the task. + */ + struct sas_task *task = qc->lldd_task; + unsigned long flags; + + qc->lldd_task = NULL; + if (task) { + /* Should this be a AT(API) device reset? */ + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags |= SAS_TASK_NEED_DEV_RESET; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + task->uldd_task = NULL; + __sas_task_abort(task); + } + } +} + +static void sas_ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct domain_device *dev = ap->private_data; + memcpy(tf, &dev->sata_dev.tf, sizeof (*tf)); +} + +static int sas_ata_scr_write(struct ata_port *ap, unsigned int sc_reg_in, + u32 val) +{ + struct domain_device *dev = ap->private_data; + + SAS_DPRINTK("STUB %s\n", __FUNCTION__); + switch (sc_reg_in) { + case SCR_STATUS: + dev->sata_dev.sstatus = val; + break; + case SCR_CONTROL: + dev->sata_dev.scontrol = val; + break; + case SCR_ERROR: + dev->sata_dev.serror = val; + break; + case SCR_ACTIVE: + dev->sata_dev.ap->link.sactive = val; + break; + default: + return -EINVAL; + } + return 0; +} + +static int sas_ata_scr_read(struct ata_port *ap, unsigned int sc_reg_in, + u32 *val) +{ + struct domain_device *dev = ap->private_data; + + SAS_DPRINTK("STUB %s\n", __FUNCTION__); + switch (sc_reg_in) { + case SCR_STATUS: + *val = dev->sata_dev.sstatus; + return 0; + case SCR_CONTROL: + *val = dev->sata_dev.scontrol; + return 0; + case SCR_ERROR: + *val = dev->sata_dev.serror; + return 0; + case SCR_ACTIVE: + *val = dev->sata_dev.ap->link.sactive; + return 0; + default: + return -EINVAL; + } +} + +static struct ata_port_operations sas_sata_ops = { + .check_status = sas_ata_check_status, + .check_altstatus = sas_ata_check_status, + .dev_select = ata_noop_dev_select, + .phy_reset = sas_ata_phy_reset, + .post_internal_cmd = sas_ata_post_internal, + .tf_read = sas_ata_tf_read, + .qc_prep = ata_noop_qc_prep, + .qc_issue = sas_ata_qc_issue, + .port_start = ata_sas_port_start, + .port_stop = ata_sas_port_stop, + .scr_read = sas_ata_scr_read, + .scr_write = sas_ata_scr_write +}; + +static struct ata_port_info sata_port_info = { + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ, + .pio_mask = 0x1f, /* PIO0-4 */ + .mwdma_mask = 0x07, /* MWDMA0-2 */ + .udma_mask = ATA_UDMA6, + .port_ops = &sas_sata_ops +}; + +int sas_ata_init_host_and_port(struct domain_device *found_dev, + struct scsi_target *starget) +{ + struct Scsi_Host *shost = dev_to_shost(&starget->dev); + struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); + struct ata_port *ap; + + ata_host_init(&found_dev->sata_dev.ata_host, + ha->dev, + sata_port_info.flags, + &sas_sata_ops); + ap = ata_sas_port_alloc(&found_dev->sata_dev.ata_host, + &sata_port_info, + shost); + if (!ap) { + SAS_DPRINTK("ata_sas_port_alloc failed.\n"); + return -ENODEV; + } + + ap->private_data = found_dev; + ap->cbl = ATA_CBL_SATA; + ap->scsi_host = shost; + found_dev->sata_dev.ap = ap; + + return 0; +} + +void sas_ata_task_abort(struct sas_task *task) +{ + struct ata_queued_cmd *qc = task->uldd_task; + struct completion *waiting; + + /* Bounce SCSI-initiated commands to the SCSI EH */ + if (qc->scsicmd) { + scsi_req_abort_cmd(qc->scsicmd); + scsi_schedule_eh(qc->scsicmd->device->host); + return; + } + + /* Internal command, fake a timeout and complete. */ + qc->flags &= ~ATA_QCFLAG_ACTIVE; + qc->flags |= ATA_QCFLAG_FAILED; + qc->err_mask |= AC_ERR_TIMEOUT; + waiting = qc->private_data; + complete(waiting); +} + +static void sas_task_timedout(unsigned long _task) +{ + struct sas_task *task = (void *) _task; + unsigned long flags; + + spin_lock_irqsave(&task->task_state_lock, flags); + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) + task->task_state_flags |= SAS_TASK_STATE_ABORTED; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + complete(&task->completion); +} + +static void sas_disc_task_done(struct sas_task *task) +{ + if (!del_timer(&task->timer)) + return; + complete(&task->completion); +} + +#define SAS_DEV_TIMEOUT 10 + +/** + * sas_execute_task -- Basic task processing for discovery + * @task: the task to be executed + * @buffer: pointer to buffer to do I/O + * @size: size of @buffer + * @dma_dir: DMA direction. DMA_xxx + */ +static int sas_execute_task(struct sas_task *task, void *buffer, int size, + enum dma_data_direction dma_dir) +{ + int res = 0; + struct scatterlist *scatter = NULL; + struct task_status_struct *ts = &task->task_status; + int num_scatter = 0; + int retries = 0; + struct sas_internal *i = + to_sas_internal(task->dev->port->ha->core.shost->transportt); + + if (dma_dir != DMA_NONE) { + scatter = kzalloc(sizeof(*scatter), GFP_KERNEL); + if (!scatter) + goto out; + + sg_init_one(scatter, buffer, size); + num_scatter = 1; + } + + task->task_proto = task->dev->tproto; + task->scatter = scatter; + task->num_scatter = num_scatter; + task->total_xfer_len = size; + task->data_dir = dma_dir; + task->task_done = sas_disc_task_done; + if (dma_dir != DMA_NONE && + sas_protocol_ata(task->task_proto)) { + task->num_scatter = dma_map_sg(task->dev->port->ha->dev, + task->scatter, + task->num_scatter, + task->data_dir); + } + + for (retries = 0; retries < 5; retries++) { + task->task_state_flags = SAS_TASK_STATE_PENDING; + init_completion(&task->completion); + + task->timer.data = (unsigned long) task; + task->timer.function = sas_task_timedout; + task->timer.expires = jiffies + SAS_DEV_TIMEOUT*HZ; + add_timer(&task->timer); + + res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); + if (res) { + del_timer(&task->timer); + SAS_DPRINTK("executing SAS discovery task failed:%d\n", + res); + goto ex_err; + } + wait_for_completion(&task->completion); + res = -ETASK; + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { + int res2; + SAS_DPRINTK("task aborted, flags:0x%x\n", + task->task_state_flags); + res2 = i->dft->lldd_abort_task(task); + SAS_DPRINTK("came back from abort task\n"); + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { + if (res2 == TMF_RESP_FUNC_COMPLETE) + continue; /* Retry the task */ + else + goto ex_err; + } + } + if (task->task_status.stat == SAM_BUSY || + task->task_status.stat == SAM_TASK_SET_FULL || + task->task_status.stat == SAS_QUEUE_FULL) { + SAS_DPRINTK("task: q busy, sleeping...\n"); + schedule_timeout_interruptible(HZ); + } else if (task->task_status.stat == SAM_CHECK_COND) { + struct scsi_sense_hdr shdr; + + if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size, + &shdr)) { + SAS_DPRINTK("couldn't normalize sense\n"); + continue; + } + if ((shdr.sense_key == 6 && shdr.asc == 0x29) || + (shdr.sense_key == 2 && shdr.asc == 4 && + shdr.ascq == 1)) { + SAS_DPRINTK("device %016llx LUN: %016llx " + "powering up or not ready yet, " + "sleeping...\n", + SAS_ADDR(task->dev->sas_addr), + SAS_ADDR(task->ssp_task.LUN)); + + schedule_timeout_interruptible(5*HZ); + } else if (shdr.sense_key == 1) { + res = 0; + break; + } else if (shdr.sense_key == 5) { + break; + } else { + SAS_DPRINTK("dev %016llx LUN: %016llx " + "sense key:0x%x ASC:0x%x ASCQ:0x%x" + "\n", + SAS_ADDR(task->dev->sas_addr), + SAS_ADDR(task->ssp_task.LUN), + shdr.sense_key, + shdr.asc, shdr.ascq); + } + } else if (task->task_status.resp != SAS_TASK_COMPLETE || + task->task_status.stat != SAM_GOOD) { + SAS_DPRINTK("task finished with resp:0x%x, " + "stat:0x%x\n", + task->task_status.resp, + task->task_status.stat); + goto ex_err; + } else { + res = 0; + break; + } + } +ex_err: + if (dma_dir != DMA_NONE) { + if (sas_protocol_ata(task->task_proto)) + dma_unmap_sg(task->dev->port->ha->dev, + task->scatter, task->num_scatter, + task->data_dir); + kfree(scatter); + } +out: + return res; +} + +/* ---------- SATA ---------- */ + +static void sas_get_ata_command_set(struct domain_device *dev) +{ + struct dev_to_host_fis *fis = + (struct dev_to_host_fis *) dev->frame_rcvd; + + if ((fis->sector_count == 1 && /* ATA */ + fis->lbal == 1 && + fis->lbam == 0 && + fis->lbah == 0 && + fis->device == 0) + || + (fis->sector_count == 0 && /* CE-ATA (mATA) */ + fis->lbal == 0 && + fis->lbam == 0xCE && + fis->lbah == 0xAA && + (fis->device & ~0x10) == 0)) + + dev->sata_dev.command_set = ATA_COMMAND_SET; + + else if ((fis->interrupt_reason == 1 && /* ATAPI */ + fis->lbal == 1 && + fis->byte_count_low == 0x14 && + fis->byte_count_high == 0xEB && + (fis->device & ~0x10) == 0)) + + dev->sata_dev.command_set = ATAPI_COMMAND_SET; + + else if ((fis->sector_count == 1 && /* SEMB */ + fis->lbal == 1 && + fis->lbam == 0x3C && + fis->lbah == 0xC3 && + fis->device == 0) + || + (fis->interrupt_reason == 1 && /* SATA PM */ + fis->lbal == 1 && + fis->byte_count_low == 0x69 && + fis->byte_count_high == 0x96 && + (fis->device & ~0x10) == 0)) + + /* Treat it as a superset? */ + dev->sata_dev.command_set = ATAPI_COMMAND_SET; +} + +/** + * sas_issue_ata_cmd -- Basic SATA command processing for discovery + * @dev: the device to send the command to + * @command: the command register + * @features: the features register + * @buffer: pointer to buffer to do I/O + * @size: size of @buffer + * @dma_dir: DMA direction. DMA_xxx + */ +static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, + u8 features, void *buffer, int size, + enum dma_data_direction dma_dir) +{ + int res = 0; + struct sas_task *task; + struct dev_to_host_fis *d2h_fis = (struct dev_to_host_fis *) + &dev->frame_rcvd[0]; + + res = -ENOMEM; + task = sas_alloc_task(GFP_KERNEL); + if (!task) + goto out; + + task->dev = dev; + + task->ata_task.fis.fis_type = 0x27; + task->ata_task.fis.command = command; + task->ata_task.fis.features = features; + task->ata_task.fis.device = d2h_fis->device; + task->ata_task.retry_count = 1; + + res = sas_execute_task(task, buffer, size, dma_dir); + + sas_free_task(task); +out: + return res; +} + +static void sas_sata_propagate_sas_addr(struct domain_device *dev) +{ + unsigned long flags; + struct asd_sas_port *port = dev->port; + struct asd_sas_phy *phy; + + BUG_ON(dev->parent); + + memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); + spin_lock_irqsave(&port->phy_list_lock, flags); + list_for_each_entry(phy, &port->phy_list, port_phy_el) + memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); + spin_unlock_irqrestore(&port->phy_list_lock, flags); +} + +#define ATA_IDENTIFY_DEV 0xEC +#define ATA_IDENTIFY_PACKET_DEV 0xA1 +#define ATA_SET_FEATURES 0xEF +#define ATA_FEATURE_PUP_STBY_SPIN_UP 0x07 + +/** + * sas_discover_sata_dev -- discover a STP/SATA device (SATA_DEV) + * @dev: STP/SATA device of interest (ATA/ATAPI) + * + * The LLDD has already been notified of this device, so that we can + * send FISes to it. Here we try to get IDENTIFY DEVICE or IDENTIFY + * PACKET DEVICE, if ATAPI device, so that the LLDD can fine-tune its + * performance for this device. + */ +static int sas_discover_sata_dev(struct domain_device *dev) +{ + int res; + __le16 *identify_x; + u8 command; + + identify_x = kzalloc(512, GFP_KERNEL); + if (!identify_x) + return -ENOMEM; + + if (dev->sata_dev.command_set == ATA_COMMAND_SET) { + dev->sata_dev.identify_device = identify_x; + command = ATA_IDENTIFY_DEV; + } else { + dev->sata_dev.identify_packet_device = identify_x; + command = ATA_IDENTIFY_PACKET_DEV; + } + + res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, + DMA_FROM_DEVICE); + if (res) + goto out_err; + + /* lives on the media? */ + if (le16_to_cpu(identify_x[0]) & 4) { + /* incomplete response */ + SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to " + "dev %llx\n", SAS_ADDR(dev->sas_addr)); + if (!le16_to_cpu(identify_x[83] & (1<<6))) + goto cont1; + res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES, + ATA_FEATURE_PUP_STBY_SPIN_UP, + NULL, 0, DMA_NONE); + if (res) + goto cont1; + + schedule_timeout_interruptible(5*HZ); /* More time? */ + res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, + DMA_FROM_DEVICE); + if (res) + goto out_err; + } +cont1: + /* Get WWN */ + if (dev->port->oob_mode != SATA_OOB_MODE) { + memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, + SAS_ADDR_SIZE); + } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && + (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) + == 0x5000) { + int i; + + for (i = 0; i < 4; i++) { + dev->sas_addr[2*i] = + (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; + dev->sas_addr[2*i+1] = + le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; + } + } + sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); + if (!dev->parent) + sas_sata_propagate_sas_addr(dev); + + /* XXX Hint: register this SATA device with SATL. + When this returns, dev->sata_dev->lu is alive and + present. + sas_satl_register_dev(dev); + */ + + sas_fill_in_rphy(dev, dev->rphy); + + return 0; +out_err: + dev->sata_dev.identify_packet_device = NULL; + dev->sata_dev.identify_device = NULL; + kfree(identify_x); + return res; +} + +static int sas_discover_sata_pm(struct domain_device *dev) +{ + return -ENODEV; +} + +/** + * sas_discover_sata -- discover an STP/SATA domain device + * @dev: pointer to struct domain_device of interest + * + * First we notify the LLDD of this device, so we can send frames to + * it. Then depending on the type of device we call the appropriate + * discover functions. Once device discover is done, we notify the + * LLDD so that it can fine-tune its parameters for the device, by + * removing it and then adding it. That is, the second time around, + * the driver would have certain fields, that it is looking at, set. + * Finally we initialize the kobj so that the device can be added to + * the system at registration time. Devices directly attached to a HA + * port, have no parents. All other devices do, and should have their + * "parent" pointer set appropriately before calling this function. + */ +int sas_discover_sata(struct domain_device *dev) +{ + int res; + + sas_get_ata_command_set(dev); + + res = sas_notify_lldd_dev_found(dev); + if (res) + return res; + + switch (dev->dev_type) { + case SATA_DEV: + res = sas_discover_sata_dev(dev); + break; + case SATA_PM: + res = sas_discover_sata_pm(dev); + break; + default: + break; + } + sas_notify_lldd_dev_gone(dev); + if (!res) { + sas_notify_lldd_dev_found(dev); + res = sas_rphy_add(dev->rphy); + } + + return res; +} diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index a65598b1e53..7ef0afc3cd6 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -22,7 +22,6 @@ * */ -#include <linux/pci.h> #include <linux/scatterlist.h> #include <scsi/scsi_host.h> #include <scsi/scsi_eh.h> @@ -55,149 +54,6 @@ void sas_init_dev(struct domain_device *dev) } } -static void sas_task_timedout(unsigned long _task) -{ - struct sas_task *task = (void *) _task; - unsigned long flags; - - spin_lock_irqsave(&task->task_state_lock, flags); - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) - task->task_state_flags |= SAS_TASK_STATE_ABORTED; - spin_unlock_irqrestore(&task->task_state_lock, flags); - - complete(&task->completion); -} - -static void sas_disc_task_done(struct sas_task *task) -{ - if (!del_timer(&task->timer)) - return; - complete(&task->completion); -} - -#define SAS_DEV_TIMEOUT 10 - -/** - * sas_execute_task -- Basic task processing for discovery - * @task: the task to be executed - * @buffer: pointer to buffer to do I/O - * @size: size of @buffer - * @pci_dma_dir: PCI_DMA_... - */ -static int sas_execute_task(struct sas_task *task, void *buffer, int size, - int pci_dma_dir) -{ - int res = 0; - struct scatterlist *scatter = NULL; - struct task_status_struct *ts = &task->task_status; - int num_scatter = 0; - int retries = 0; - struct sas_internal *i = - to_sas_internal(task->dev->port->ha->core.shost->transportt); - - if (pci_dma_dir != PCI_DMA_NONE) { - scatter = kzalloc(sizeof(*scatter), GFP_KERNEL); - if (!scatter) - goto out; - - sg_init_one(scatter, buffer, size); - num_scatter = 1; - } - - task->task_proto = task->dev->tproto; - task->scatter = scatter; - task->num_scatter = num_scatter; - task->total_xfer_len = size; - task->data_dir = pci_dma_dir; - task->task_done = sas_disc_task_done; - - for (retries = 0; retries < 5; retries++) { - task->task_state_flags = SAS_TASK_STATE_PENDING; - init_completion(&task->completion); - - task->timer.data = (unsigned long) task; - task->timer.function = sas_task_timedout; - task->timer.expires = jiffies + SAS_DEV_TIMEOUT*HZ; - add_timer(&task->timer); - - res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); - if (res) { - del_timer(&task->timer); - SAS_DPRINTK("executing SAS discovery task failed:%d\n", - res); - goto ex_err; - } - wait_for_completion(&task->completion); - res = -ETASK; - if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { - int res2; - SAS_DPRINTK("task aborted, flags:0x%x\n", - task->task_state_flags); - res2 = i->dft->lldd_abort_task(task); - SAS_DPRINTK("came back from abort task\n"); - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - if (res2 == TMF_RESP_FUNC_COMPLETE) - continue; /* Retry the task */ - else - goto ex_err; - } - } - if (task->task_status.stat == SAM_BUSY || - task->task_status.stat == SAM_TASK_SET_FULL || - task->task_status.stat == SAS_QUEUE_FULL) { - SAS_DPRINTK("task: q busy, sleeping...\n"); - schedule_timeout_interruptible(HZ); - } else if (task->task_status.stat == SAM_CHECK_COND) { - struct scsi_sense_hdr shdr; - - if (!scsi_normalize_sense(ts->buf, ts->buf_valid_size, - &shdr)) { - SAS_DPRINTK("couldn't normalize sense\n"); - continue; - } - if ((shdr.sense_key == 6 && shdr.asc == 0x29) || - (shdr.sense_key == 2 && shdr.asc == 4 && - shdr.ascq == 1)) { - SAS_DPRINTK("device %016llx LUN: %016llx " - "powering up or not ready yet, " - "sleeping...\n", - SAS_ADDR(task->dev->sas_addr), - SAS_ADDR(task->ssp_task.LUN)); - - schedule_timeout_interruptible(5*HZ); - } else if (shdr.sense_key == 1) { - res = 0; - break; - } else if (shdr.sense_key == 5) { - break; - } else { - SAS_DPRINTK("dev %016llx LUN: %016llx " - "sense key:0x%x ASC:0x%x ASCQ:0x%x" - "\n", - SAS_ADDR(task->dev->sas_addr), - SAS_ADDR(task->ssp_task.LUN), - shdr.sense_key, - shdr.asc, shdr.ascq); - } - } else if (task->task_status.resp != SAS_TASK_COMPLETE || - task->task_status.stat != SAM_GOOD) { - SAS_DPRINTK("task finished with resp:0x%x, " - "stat:0x%x\n", - task->task_status.resp, - task->task_status.stat); - goto ex_err; - } else { - res = 0; - break; - } - } -ex_err: - if (pci_dma_dir != PCI_DMA_NONE) - kfree(scatter); -out: - return res; -} - /* ---------- Domain device discovery ---------- */ /** @@ -255,6 +111,7 @@ static int sas_get_port_device(struct asd_sas_port *port) switch (dev->dev_type) { case SAS_END_DEV: + case SATA_DEV: rphy = sas_end_device_alloc(port->port); break; case EDGE_DEV: @@ -265,7 +122,6 @@ static int sas_get_port_device(struct asd_sas_port *port) rphy = sas_expander_alloc(port->port, SAS_FANOUT_EXPANDER_DEVICE); break; - case SATA_DEV: default: printk("ERROR: Unidentified device type %d\n", dev->dev_type); rphy = NULL; @@ -292,207 +148,15 @@ static int sas_get_port_device(struct asd_sas_port *port) port->disc.max_level = 0; dev->rphy = rphy; - spin_lock(&port->dev_list_lock); + spin_lock_irq(&port->dev_list_lock); list_add_tail(&dev->dev_list_node, &port->dev_list); - spin_unlock(&port->dev_list_lock); + spin_unlock_irq(&port->dev_list_lock); return 0; } /* ---------- Discover and Revalidate ---------- */ -/* ---------- SATA ---------- */ - -static void sas_get_ata_command_set(struct domain_device *dev) -{ - struct dev_to_host_fis *fis = - (struct dev_to_host_fis *) dev->frame_rcvd; - - if ((fis->sector_count == 1 && /* ATA */ - fis->lbal == 1 && - fis->lbam == 0 && - fis->lbah == 0 && - fis->device == 0) - || - (fis->sector_count == 0 && /* CE-ATA (mATA) */ - fis->lbal == 0 && - fis->lbam == 0xCE && - fis->lbah == 0xAA && - (fis->device & ~0x10) == 0)) - - dev->sata_dev.command_set = ATA_COMMAND_SET; - - else if ((fis->interrupt_reason == 1 && /* ATAPI */ - fis->lbal == 1 && - fis->byte_count_low == 0x14 && - fis->byte_count_high == 0xEB && - (fis->device & ~0x10) == 0)) - - dev->sata_dev.command_set = ATAPI_COMMAND_SET; - - else if ((fis->sector_count == 1 && /* SEMB */ - fis->lbal == 1 && - fis->lbam == 0x3C && - fis->lbah == 0xC3 && - fis->device == 0) - || - (fis->interrupt_reason == 1 && /* SATA PM */ - fis->lbal == 1 && - fis->byte_count_low == 0x69 && - fis->byte_count_high == 0x96 && - (fis->device & ~0x10) == 0)) - - /* Treat it as a superset? */ - dev->sata_dev.command_set = ATAPI_COMMAND_SET; -} - -/** - * sas_issue_ata_cmd -- Basic SATA command processing for discovery - * @dev: the device to send the command to - * @command: the command register - * @features: the features register - * @buffer: pointer to buffer to do I/O - * @size: size of @buffer - * @pci_dma_dir: PCI_DMA_... - */ -static int sas_issue_ata_cmd(struct domain_device *dev, u8 command, - u8 features, void *buffer, int size, - int pci_dma_dir) -{ - int res = 0; - struct sas_task *task; - struct dev_to_host_fis *d2h_fis = (struct dev_to_host_fis *) - &dev->frame_rcvd[0]; - - res = -ENOMEM; - task = sas_alloc_task(GFP_KERNEL); - if (!task) - goto out; - - task->dev = dev; - - task->ata_task.fis.command = command; - task->ata_task.fis.features = features; - task->ata_task.fis.device = d2h_fis->device; - task->ata_task.retry_count = 1; - - res = sas_execute_task(task, buffer, size, pci_dma_dir); - - sas_free_task(task); -out: - return res; -} - -static void sas_sata_propagate_sas_addr(struct domain_device *dev) -{ - unsigned long flags; - struct asd_sas_port *port = dev->port; - struct asd_sas_phy *phy; - - BUG_ON(dev->parent); - - memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); - spin_lock_irqsave(&port->phy_list_lock, flags); - list_for_each_entry(phy, &port->phy_list, port_phy_el) - memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); - spin_unlock_irqrestore(&port->phy_list_lock, flags); -} - -#define ATA_IDENTIFY_DEV 0xEC -#define ATA_IDENTIFY_PACKET_DEV 0xA1 -#define ATA_SET_FEATURES 0xEF -#define ATA_FEATURE_PUP_STBY_SPIN_UP 0x07 - -/** - * sas_discover_sata_dev -- discover a STP/SATA device (SATA_DEV) - * @dev: STP/SATA device of interest (ATA/ATAPI) - * - * The LLDD has already been notified of this device, so that we can - * send FISes to it. Here we try to get IDENTIFY DEVICE or IDENTIFY - * PACKET DEVICE, if ATAPI device, so that the LLDD can fine-tune its - * performance for this device. - */ -static int sas_discover_sata_dev(struct domain_device *dev) -{ - int res; - __le16 *identify_x; - u8 command; - - identify_x = kzalloc(512, GFP_KERNEL); - if (!identify_x) - return -ENOMEM; - - if (dev->sata_dev.command_set == ATA_COMMAND_SET) { - dev->sata_dev.identify_device = identify_x; - command = ATA_IDENTIFY_DEV; - } else { - dev->sata_dev.identify_packet_device = identify_x; - command = ATA_IDENTIFY_PACKET_DEV; - } - - res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, - PCI_DMA_FROMDEVICE); - if (res) - goto out_err; - - /* lives on the media? */ - if (le16_to_cpu(identify_x[0]) & 4) { - /* incomplete response */ - SAS_DPRINTK("sending SET FEATURE/PUP_STBY_SPIN_UP to " - "dev %llx\n", SAS_ADDR(dev->sas_addr)); - if (!le16_to_cpu(identify_x[83] & (1<<6))) - goto cont1; - res = sas_issue_ata_cmd(dev, ATA_SET_FEATURES, - ATA_FEATURE_PUP_STBY_SPIN_UP, - NULL, 0, PCI_DMA_NONE); - if (res) - goto cont1; - - schedule_timeout_interruptible(5*HZ); /* More time? */ - res = sas_issue_ata_cmd(dev, command, 0, identify_x, 512, - PCI_DMA_FROMDEVICE); - if (res) - goto out_err; - } -cont1: - /* Get WWN */ - if (dev->port->oob_mode != SATA_OOB_MODE) { - memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, - SAS_ADDR_SIZE); - } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && - (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) - == 0x5000) { - int i; - - for (i = 0; i < 4; i++) { - dev->sas_addr[2*i] = - (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; - dev->sas_addr[2*i+1] = - le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; - } - } - sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); - if (!dev->parent) - sas_sata_propagate_sas_addr(dev); - - /* XXX Hint: register this SATA device with SATL. - When this returns, dev->sata_dev->lu is alive and - present. - sas_satl_register_dev(dev); - */ - return 0; -out_err: - dev->sata_dev.identify_packet_device = NULL; - dev->sata_dev.identify_device = NULL; - kfree(identify_x); - return res; -} - -static int sas_discover_sata_pm(struct domain_device *dev) -{ - return -ENODEV; -} - int sas_notify_lldd_dev_found(struct domain_device *dev) { int res = 0; @@ -505,7 +169,7 @@ int sas_notify_lldd_dev_found(struct domain_device *dev) if (res) { printk("sas: driver on pcidev %s cannot handle " "device %llx, error:%d\n", - pci_name(sas_ha->pcidev), + sas_ha->dev->bus_id, SAS_ADDR(dev->sas_addr), res); } } @@ -525,60 +189,6 @@ void sas_notify_lldd_dev_gone(struct domain_device *dev) /* ---------- Common/dispatchers ---------- */ -/** - * sas_discover_sata -- discover an STP/SATA domain device - * @dev: pointer to struct domain_device of interest - * - * First we notify the LLDD of this device, so we can send frames to - * it. Then depending on the type of device we call the appropriate - * discover functions. Once device discover is done, we notify the - * LLDD so that it can fine-tune its parameters for the device, by - * removing it and then adding it. That is, the second time around, - * the driver would have certain fields, that it is looking at, set. - * Finally we initialize the kobj so that the device can be added to - * the system at registration time. Devices directly attached to a HA - * port, have no parents. All other devices do, and should have their - * "parent" pointer set appropriately before calling this function. - */ -int sas_discover_sata(struct domain_device *dev) -{ - int res; - - sas_get_ata_command_set(dev); - - res = sas_notify_lldd_dev_found(dev); - if (res) - goto out_err2; - - switch (dev->dev_type) { - case SATA_DEV: - res = sas_discover_sata_dev(dev); - break; - case SATA_PM: - res = sas_discover_sata_pm(dev); - break; - default: - break; - } - if (res) - goto out_err; - - sas_notify_lldd_dev_gone(dev); - res = sas_notify_lldd_dev_found(dev); - if (res) - goto out_err2; - - res = sas_rphy_add(dev->rphy); - if (res) - goto out_err; - - return res; - -out_err: - sas_notify_lldd_dev_gone(dev); -out_err2: - return res; -} /** * sas_discover_end_dev -- discover an end device (SSP, etc) @@ -685,11 +295,14 @@ static void sas_discover_domain(struct work_struct *work) case FANOUT_DEV: error = sas_discover_root_expander(dev); break; +#ifdef CONFIG_SCSI_SAS_ATA case SATA_DEV: case SATA_PM: error = sas_discover_sata(dev); break; +#endif default: + error = -ENXIO; SAS_DPRINTK("unhandled device %d\n", dev->dev_type); break; } @@ -698,9 +311,9 @@ static void sas_discover_domain(struct work_struct *work) sas_rphy_free(dev->rphy); dev->rphy = NULL; - spin_lock(&port->dev_list_lock); + spin_lock_irq(&port->dev_list_lock); list_del_init(&dev->dev_list_node); - spin_unlock(&port->dev_list_lock); + spin_unlock_irq(&port->dev_list_lock); kfree(dev); /* not kobject_register-ed yet */ port->port_dev = NULL; diff --git a/drivers/scsi/libsas/sas_dump.c b/drivers/scsi/libsas/sas_dump.c index f1246d2c9be..bf34a236f94 100644 --- a/drivers/scsi/libsas/sas_dump.c +++ b/drivers/scsi/libsas/sas_dump.c @@ -56,7 +56,7 @@ void sas_dprint_phye(int phyid, enum phy_event pe) void sas_dprint_hae(struct sas_ha_struct *sas_ha, enum ha_event he) { - SAS_DPRINTK("ha %s: %s event\n", pci_name(sas_ha->pcidev), + SAS_DPRINTK("ha %s: %s event\n", sas_ha->dev->bus_id, sas_hae_str[he]); } diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 23e90c5f8f3..8727436b222 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -23,6 +23,7 @@ */ #include <linux/scatterlist.h> +#include <linux/blkdev.h> #include "sas_internal.h" @@ -36,14 +37,6 @@ static int sas_configure_phy(struct domain_device *dev, int phy_id, u8 *sas_addr, int include); static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); -#if 0 -/* FIXME: smp needs to migrate into the sas class */ -static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *, - char *, loff_t, size_t); -static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *, - char *, loff_t, size_t); -#endif - /* ---------- SMP task management ---------- */ static void smp_task_timedout(unsigned long _task) @@ -220,6 +213,36 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, #define DISCOVER_REQ_SIZE 16 #define DISCOVER_RESP_SIZE 56 +static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req, + u8 *disc_resp, int single) +{ + int i, res; + + disc_req[9] = single; + for (i = 1 ; i < 3; i++) { + struct discover_resp *dr; + + res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE, + disc_resp, DISCOVER_RESP_SIZE); + if (res) + return res; + /* This is detecting a failure to transmit inital + * dev to host FIS as described in section G.5 of + * sas-2 r 04b */ + dr = &((struct smp_resp *)disc_resp)->disc; + if (!(dr->attached_dev_type == 0 && + dr->attached_sata_dev)) + break; + /* In order to generate the dev to host FIS, we + * send a link reset to the expander port */ + sas_smp_phy_control(dev, single, PHY_FUNC_LINK_RESET, NULL); + /* Wait for the reset to trigger the negotiation */ + msleep(500); + } + sas_set_ex_phy(dev, single, disc_resp); + return 0; +} + static int sas_ex_phy_discover(struct domain_device *dev, int single) { struct expander_device *ex = &dev->ex_dev; @@ -240,23 +263,15 @@ static int sas_ex_phy_discover(struct domain_device *dev, int single) disc_req[1] = SMP_DISCOVER; if (0 <= single && single < ex->num_phys) { - disc_req[9] = single; - res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE, - disc_resp, DISCOVER_RESP_SIZE); - if (res) - goto out_err; - sas_set_ex_phy(dev, single, disc_resp); + res = sas_ex_phy_discover_helper(dev, disc_req, disc_resp, single); } else { int i; for (i = 0; i < ex->num_phys; i++) { - disc_req[9] = i; - res = smp_execute_task(dev, disc_req, - DISCOVER_REQ_SIZE, disc_resp, - DISCOVER_RESP_SIZE); + res = sas_ex_phy_discover_helper(dev, disc_req, + disc_resp, i); if (res) goto out_err; - sas_set_ex_phy(dev, i, disc_resp); } } out_err: @@ -492,13 +507,20 @@ static int sas_dev_present_in_domain(struct asd_sas_port *port, int sas_smp_get_phy_events(struct sas_phy *phy) { int res; + u8 *req; + u8 *resp; struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); struct domain_device *dev = sas_find_dev_by_rphy(rphy); - u8 *req = alloc_smp_req(RPEL_REQ_SIZE); - u8 *resp = kzalloc(RPEL_RESP_SIZE, GFP_KERNEL); - if (!resp) + req = alloc_smp_req(RPEL_REQ_SIZE); + if (!req) + return -ENOMEM; + + resp = alloc_smp_resp(RPEL_RESP_SIZE); + if (!resp) { + kfree(req); return -ENOMEM; + } req[1] = SMP_REPORT_PHY_ERR_LOG; req[9] = phy->number; @@ -520,6 +542,8 @@ int sas_smp_get_phy_events(struct sas_phy *phy) } +#ifdef CONFIG_SCSI_SAS_ATA + #define RPS_REQ_SIZE 16 #define RPS_RESP_SIZE 60 @@ -529,6 +553,7 @@ static int sas_get_report_phy_sata(struct domain_device *dev, { int res; u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE); + u8 *resp = (u8 *)rps_resp; if (!rps_req) return -ENOMEM; @@ -539,9 +564,30 @@ static int sas_get_report_phy_sata(struct domain_device *dev, res = smp_execute_task(dev, rps_req, RPS_REQ_SIZE, rps_resp, RPS_RESP_SIZE); + /* 0x34 is the FIS type for the D2H fis. There's a potential + * standards cockup here. sas-2 explicitly specifies the FIS + * should be encoded so that FIS type is in resp[24]. + * However, some expanders endian reverse this. Undo the + * reversal here */ + if (!res && resp[27] == 0x34 && resp[24] != 0x34) { + int i; + + for (i = 0; i < 5; i++) { + int j = 24 + (i*4); + u8 a, b; + a = resp[j + 0]; + b = resp[j + 1]; + resp[j + 0] = resp[j + 3]; + resp[j + 1] = resp[j + 2]; + resp[j + 2] = b; + resp[j + 3] = a; + } + } + kfree(rps_req); - return 0; + return res; } +#endif static void sas_ex_get_linkrate(struct domain_device *parent, struct domain_device *child, @@ -609,6 +655,7 @@ static struct domain_device *sas_ex_discover_end_dev( } sas_ex_get_linkrate(parent, child, phy); +#ifdef CONFIG_SCSI_SAS_ATA if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { child->dev_type = SATA_DEV; if (phy->attached_tproto & SAS_PROTO_STP) @@ -625,16 +672,30 @@ static struct domain_device *sas_ex_discover_end_dev( } memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, sizeof(struct dev_to_host_fis)); + + rphy = sas_end_device_alloc(phy->port); + if (unlikely(!rphy)) + goto out_free; + sas_init_dev(child); + + child->rphy = rphy; + + spin_lock_irq(&parent->port->dev_list_lock); + list_add_tail(&child->dev_list_node, &parent->port->dev_list); + spin_unlock_irq(&parent->port->dev_list_lock); + res = sas_discover_sata(child); if (res) { SAS_DPRINTK("sas_discover_sata() for device %16llx at " "%016llx:0x%x returned 0x%x\n", SAS_ADDR(child->sas_addr), SAS_ADDR(parent->sas_addr), phy_id, res); - goto out_free; + goto out_list_del; } - } else if (phy->attached_tproto & SAS_PROTO_SSP) { + } else +#endif + if (phy->attached_tproto & SAS_PROTO_SSP) { child->dev_type = SAS_END_DEV; rphy = sas_end_device_alloc(phy->port); /* FIXME: error handling */ @@ -646,9 +707,9 @@ static struct domain_device *sas_ex_discover_end_dev( child->rphy = rphy; sas_fill_in_rphy(child, rphy); - spin_lock(&parent->port->dev_list_lock); + spin_lock_irq(&parent->port->dev_list_lock); list_add_tail(&child->dev_list_node, &parent->port->dev_list); - spin_unlock(&parent->port->dev_list_lock); + spin_unlock_irq(&parent->port->dev_list_lock); res = sas_discover_end_dev(child); if (res) { @@ -662,6 +723,7 @@ static struct domain_device *sas_ex_discover_end_dev( SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", phy->attached_tproto, SAS_ADDR(parent->sas_addr), phy_id); + goto out_free; } list_add_tail(&child->siblings, &parent_ex->children); @@ -761,9 +823,9 @@ static struct domain_device *sas_ex_discover_expander( sas_fill_in_rphy(child, rphy); sas_rphy_add(rphy); - spin_lock(&parent->port->dev_list_lock); + spin_lock_irq(&parent->port->dev_list_lock); list_add_tail(&child->dev_list_node, &parent->port->dev_list); - spin_unlock(&parent->port->dev_list_lock); + spin_unlock_irq(&parent->port->dev_list_lock); res = sas_discover_expander(child); if (res) { @@ -1359,30 +1421,6 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr) return 0; } -#if 0 -#define SMP_BIN_ATTR_NAME "smp_portal" - -static void sas_ex_smp_hook(struct domain_device *dev) -{ - struct expander_device *ex_dev = &dev->ex_dev; - struct bin_attribute *bin_attr = &ex_dev->smp_bin_attr; - - memset(bin_attr, 0, sizeof(*bin_attr)); - - bin_attr->attr.name = SMP_BIN_ATTR_NAME; - bin_attr->attr.mode = 0600; - - bin_attr->size = 0; - bin_attr->private = NULL; - bin_attr->read = smp_portal_read; - bin_attr->write= smp_portal_write; - bin_attr->mmap = NULL; - - ex_dev->smp_portal_pid = -1; - init_MUTEX(&ex_dev->smp_sema); -} -#endif - /** * sas_discover_expander -- expander discovery * @ex: pointer to expander domain device @@ -1844,76 +1882,50 @@ out: return res; } -#if 0 -/* ---------- SMP portal ---------- */ - -static ssize_t smp_portal_write(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t offs, size_t size) +int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, + struct request *req) { - struct domain_device *dev = to_dom_device(kobj); - struct expander_device *ex = &dev->ex_dev; - - if (offs != 0) - return -EFBIG; - else if (size == 0) - return 0; + struct domain_device *dev; + int ret, type; + struct request *rsp = req->next_rq; - down_interruptible(&ex->smp_sema); - if (ex->smp_req) - kfree(ex->smp_req); - ex->smp_req = kzalloc(size, GFP_USER); - if (!ex->smp_req) { - up(&ex->smp_sema); - return -ENOMEM; + if (!rsp) { + printk("%s: space for a smp response is missing\n", + __FUNCTION__); + return -EINVAL; } - memcpy(ex->smp_req, buf, size); - ex->smp_req_size = size; - ex->smp_portal_pid = current->pid; - up(&ex->smp_sema); - return size; -} - -static ssize_t smp_portal_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t offs, size_t size) -{ - struct domain_device *dev = to_dom_device(kobj); - struct expander_device *ex = &dev->ex_dev; - u8 *smp_resp; - int res = -EINVAL; - - /* XXX: sysfs gives us an offset of 0x10 or 0x8 while in fact - * it should be 0. - */ + /* no rphy means no smp target support (ie aic94xx host) */ + if (!rphy) { + printk("%s: can we send a smp request to a host?\n", + __FUNCTION__); + return -EINVAL; + } + type = rphy->identify.device_type; - down_interruptible(&ex->smp_sema); - if (!ex->smp_req || ex->smp_portal_pid != current->pid) - goto out; + if (type != SAS_EDGE_EXPANDER_DEVICE && + type != SAS_FANOUT_EXPANDER_DEVICE) { + printk("%s: can we send a smp request to a device?\n", + __FUNCTION__); + return -EINVAL; + } - res = 0; - if (size == 0) - goto out; + dev = sas_find_dev_by_rphy(rphy); + if (!dev) { + printk("%s: fail to find a domain_device?\n", __FUNCTION__); + return -EINVAL; + } - res = -ENOMEM; - smp_resp = alloc_smp_resp(size); - if (!smp_resp) - goto out; - res = smp_execute_task(dev, ex->smp_req, ex->smp_req_size, - smp_resp, size); - if (!res) { - memcpy(buf, smp_resp, size); - res = size; + /* do we need to support multiple segments? */ + if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { + printk("%s: multiple segments req %u %u, rsp %u %u\n", + __FUNCTION__, req->bio->bi_vcnt, req->data_len, + rsp->bio->bi_vcnt, rsp->data_len); + return -EINVAL; } - kfree(smp_resp); -out: - kfree(ex->smp_req); - ex->smp_req = NULL; - ex->smp_req_size = 0; - ex->smp_portal_pid = -1; - up(&ex->smp_sema); - return res; + ret = smp_execute_task(dev, bio_data(req->bio), req->data_len, + bio_data(rsp->bio), rsp->data_len); + + return ret; } -#endif diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 965698c8b7b..9cd5abe9e71 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c @@ -259,6 +259,7 @@ static struct sas_function_template sft = { .phy_reset = sas_phy_reset, .set_phy_speed = sas_set_phy_speed, .get_linkerrors = sas_get_linkerrors, + .smp_handler = sas_smp_handler, }; struct scsi_transport_template * @@ -292,7 +293,7 @@ EXPORT_SYMBOL_GPL(sas_domain_release_transport); static int __init sas_class_init(void) { sas_task_cache = kmem_cache_create("sas_task", sizeof(struct sas_task), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + 0, SLAB_HWCACHE_ALIGN, NULL); if (!sas_task_cache) return -ENOMEM; diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index a78638df201..2b8213b1832 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h @@ -39,6 +39,9 @@ #define SAS_DPRINTK(fmt, ...) #endif +#define TO_SAS_TASK(_scsi_cmd) ((void *)(_scsi_cmd)->host_scribble) +#define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0) + void sas_scsi_recover_host(struct Scsi_Host *shost); int sas_show_class(enum sas_class class, char *buf); diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 9c5342e7a69..7663841eb4c 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -34,6 +34,7 @@ #include <scsi/scsi_eh.h> #include <scsi/scsi_transport.h> #include <scsi/scsi_transport_sas.h> +#include <scsi/sas_ata.h> #include "../scsi_sas_internal.h" #include "../scsi_transport_api.h" #include "../scsi_priv.h" @@ -42,12 +43,10 @@ #include <linux/blkdev.h> #include <linux/freezer.h> #include <linux/scatterlist.h> +#include <linux/libata.h> /* ---------- SCSI Host glue ---------- */ -#define TO_SAS_TASK(_scsi_cmd) ((void *)(_scsi_cmd)->host_scribble) -#define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0) - static void sas_scsi_task_done(struct sas_task *task) { struct task_status_struct *ts = &task->task_status; @@ -172,7 +171,7 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd, return task; } -static int sas_queue_up(struct sas_task *task) +int sas_queue_up(struct sas_task *task) { struct sas_ha_struct *sas_ha = task->dev->port->ha; struct scsi_core *core = &sas_ha->core; @@ -213,6 +212,16 @@ int sas_queuecommand(struct scsi_cmnd *cmd, struct sas_ha_struct *sas_ha = dev->port->ha; struct sas_task *task; + if (dev_is_sata(dev)) { + unsigned long flags; + + spin_lock_irqsave(dev->sata_dev.ap->lock, flags); + res = ata_sas_queuecmd(cmd, scsi_done, + dev->sata_dev.ap); + spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags); + goto out; + } + res = -ENOMEM; task = sas_create_task(cmd, dev, GFP_ATOMIC); if (!task) @@ -684,6 +693,16 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) return EH_NOT_HANDLED; } +int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) +{ + struct domain_device *dev = sdev_to_domain_dev(sdev); + + if (dev_is_sata(dev)) + return ata_scsi_ioctl(sdev, cmd, arg); + + return -EINVAL; +} + struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy) { struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent); @@ -723,10 +742,17 @@ static inline struct domain_device *sas_find_target(struct scsi_target *starget) int sas_target_alloc(struct scsi_target *starget) { struct domain_device *found_dev = sas_find_target(starget); + int res; if (!found_dev) return -ENODEV; + if (dev_is_sata(found_dev)) { + res = sas_ata_init_host_and_port(found_dev, starget); + if (res) + return res; + } + starget->hostdata = found_dev; return 0; } @@ -741,6 +767,11 @@ int sas_slave_configure(struct scsi_device *scsi_dev) BUG_ON(dev->rphy->identify.device_type != SAS_END_DEVICE); + if (dev_is_sata(dev)) { + ata_sas_slave_configure(scsi_dev, dev->sata_dev.ap); + return 0; + } + sas_ha = dev->port->ha; sas_read_port_mode_page(scsi_dev); @@ -764,6 +795,10 @@ int sas_slave_configure(struct scsi_device *scsi_dev) void sas_slave_destroy(struct scsi_device *scsi_dev) { + struct domain_device *dev = sdev_to_domain_dev(scsi_dev); + + if (dev_is_sata(dev)) + ata_port_disable(dev->sata_dev.ap); } int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth) @@ -980,10 +1015,38 @@ void sas_task_abort(struct sas_task *task) return; } + if (dev_is_sata(task->dev)) { + sas_ata_task_abort(task); + return; + } + scsi_req_abort_cmd(sc); scsi_schedule_eh(sc->device->host); } +int sas_slave_alloc(struct scsi_device *scsi_dev) +{ + struct domain_device *dev = sdev_to_domain_dev(scsi_dev); + + if (dev_is_sata(dev)) + return ata_sas_port_init(dev->sata_dev.ap); + + return 0; +} + +void sas_target_destroy(struct scsi_target *starget) +{ + struct domain_device *found_dev = sas_find_target(starget); + + if (!found_dev) + return; + + if (dev_is_sata(found_dev)) + ata_sas_port_destroy(found_dev->sata_dev.ap); + + return; +} + EXPORT_SYMBOL_GPL(sas_queuecommand); EXPORT_SYMBOL_GPL(sas_target_alloc); EXPORT_SYMBOL_GPL(sas_slave_configure); @@ -997,3 +1060,6 @@ EXPORT_SYMBOL_GPL(sas_phy_reset); EXPORT_SYMBOL_GPL(sas_phy_enable); EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); +EXPORT_SYMBOL_GPL(sas_slave_alloc); +EXPORT_SYMBOL_GPL(sas_target_destroy); +EXPORT_SYMBOL_GPL(sas_ioctl); diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index f8f64d6485c..ba3ecab9baf 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -45,7 +45,7 @@ struct lpfc_sli2_slim; #define LPFC_DISC_IOCB_BUFF_COUNT 20 #define LPFC_HB_MBOX_INTERVAL 5 /* Heart beat interval in seconds. */ -#define LPFC_HB_MBOX_TIMEOUT 30 /* Heart beat timeout in seconds. */ +#define LPFC_HB_MBOX_TIMEOUT 30 /* Heart beat timeout in seconds. */ /* Define macros for 64 bit support */ #define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr))) @@ -78,6 +78,7 @@ struct lpfc_dma_pool { struct hbq_dmabuf { struct lpfc_dmabuf dbuf; + uint32_t size; uint32_t tag; }; @@ -329,13 +330,30 @@ struct lpfc_vport { #define FC_LOADING 0x1 /* HBA in process of loading drvr */ #define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */ char *vname; /* Application assigned name */ + + /* Vport Config Parameters */ + uint32_t cfg_scan_down; + uint32_t cfg_lun_queue_depth; + uint32_t cfg_nodev_tmo; + uint32_t cfg_devloss_tmo; + uint32_t cfg_restrict_login; + uint32_t cfg_peer_port_login; + uint32_t cfg_fcp_class; + uint32_t cfg_use_adisc; + uint32_t cfg_fdmi_on; + uint32_t cfg_discovery_threads; + uint32_t cfg_log_verbose; + uint32_t cfg_max_luns; + + uint32_t dev_loss_tmo_changed; + struct fc_vport *fc_vport; #ifdef CONFIG_LPFC_DEBUG_FS struct dentry *debug_disc_trc; struct dentry *debug_nodelist; struct dentry *vport_debugfs_root; - struct lpfc_disc_trc *disc_trc; + struct lpfc_debugfs_trc *disc_trc; atomic_t disc_trc_cnt; #endif }; @@ -345,17 +363,25 @@ struct hbq_s { uint32_t next_hbqPutIdx; /* Index to next HBQ slot to use */ uint32_t hbqPutIdx; /* HBQ slot to use */ uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */ + void *hbq_virt; /* Virtual ptr to this hbq */ + struct list_head hbq_buffer_list; /* buffers assigned to this HBQ */ + /* Callback for HBQ buffer allocation */ + struct hbq_dmabuf *(*hbq_alloc_buffer) (struct lpfc_hba *); + /* Callback for HBQ buffer free */ + void (*hbq_free_buffer) (struct lpfc_hba *, + struct hbq_dmabuf *); }; -#define LPFC_MAX_HBQS 16 -/* this matches the possition in the lpfc_hbq_defs array */ +#define LPFC_MAX_HBQS 4 +/* this matches the position in the lpfc_hbq_defs array */ #define LPFC_ELS_HBQ 0 +#define LPFC_EXTRA_HBQ 1 struct lpfc_hba { struct lpfc_sli sli; uint32_t sli_rev; /* SLI2 or SLI3 */ uint32_t sli3_options; /* Mask of enabled SLI3 options */ -#define LPFC_SLI3_ENABLED 0x01 +#define LPFC_SLI3_ENABLED 0x01 #define LPFC_SLI3_HBQ_ENABLED 0x02 #define LPFC_SLI3_NPIV_ENABLED 0x04 #define LPFC_SLI3_VPORT_TEARDOWN 0x08 @@ -364,7 +390,7 @@ struct lpfc_hba { enum hba_state link_state; uint32_t link_flag; /* link state flags */ -#define LS_LOOPBACK_MODE 0x1 /* NPort is in Loopback mode */ +#define LS_LOOPBACK_MODE 0x1 /* NPort is in Loopback mode */ /* This flag is set while issuing */ /* INIT_LINK mailbox command */ #define LS_NPIV_FAB_SUPPORTED 0x2 /* Fabric supports NPIV */ @@ -413,28 +439,16 @@ struct lpfc_hba { uint8_t wwpn[8]; uint32_t RandomData[7]; - uint32_t cfg_log_verbose; - uint32_t cfg_lun_queue_depth; - uint32_t cfg_nodev_tmo; - uint32_t cfg_devloss_tmo; - uint32_t cfg_hba_queue_depth; - uint32_t cfg_peer_port_login; - uint32_t cfg_vport_restrict_login; - uint32_t cfg_npiv_enable; - uint32_t cfg_fcp_class; - uint32_t cfg_use_adisc; + /* HBA Config Parameters */ uint32_t cfg_ack0; + uint32_t cfg_enable_npiv; uint32_t cfg_topology; - uint32_t cfg_scan_down; uint32_t cfg_link_speed; uint32_t cfg_cr_delay; uint32_t cfg_cr_count; uint32_t cfg_multi_ring_support; uint32_t cfg_multi_ring_rctl; uint32_t cfg_multi_ring_type; - uint32_t cfg_fdmi_on; - uint32_t cfg_discovery_threads; - uint32_t cfg_max_luns; uint32_t cfg_poll; uint32_t cfg_poll_tmo; uint32_t cfg_use_msi; @@ -442,8 +456,8 @@ struct lpfc_hba { uint32_t cfg_sg_dma_buf_size; uint64_t cfg_soft_wwnn; uint64_t cfg_soft_wwpn; + uint32_t cfg_hba_queue_depth; - uint32_t dev_loss_tmo_changed; lpfc_vpd_t vpd; /* vital product data */ @@ -457,7 +471,6 @@ struct lpfc_hba { wait_queue_head_t *work_wait; struct task_struct *worker_thread; - struct list_head hbq_buffer_list; uint32_t hbq_count; /* Count of configured HBQs */ struct hbq_s hbqs[LPFC_MAX_HBQS]; /* local copy of hbq indicies */ @@ -526,12 +539,14 @@ struct lpfc_hba { mempool_t *nlp_mem_pool; struct fc_host_statistics link_stats; + uint8_t using_msi; struct list_head port_list; - struct lpfc_vport *pport; /* physical lpfc_vport pointer */ - uint16_t max_vpi; /* Maximum virtual nports */ -#define LPFC_MAX_VPI 100 /* Max number of VPorts supported */ - unsigned long *vpi_bmask; /* vpi allocation table */ + struct lpfc_vport *pport; /* physical lpfc_vport pointer */ + uint16_t max_vpi; /* Maximum virtual nports */ +#define LPFC_MAX_VPI 100 /* Max number of VPI supported */ +#define LPFC_MAX_VPORTS (LPFC_MAX_VPI+1)/* Max number of VPorts supported */ + unsigned long *vpi_bmask; /* vpi allocation table */ /* Data structure used by fabric iocb scheduler */ struct list_head fabric_iocb_list; @@ -547,6 +562,11 @@ struct lpfc_hba { #ifdef CONFIG_LPFC_DEBUG_FS struct dentry *hba_debugfs_root; atomic_t debugfs_vport_count; + struct dentry *debug_hbqinfo; + struct dentry *debug_dumpslim; + struct dentry *debug_slow_ring_trc; + struct lpfc_debugfs_trc *slow_ring_trc; + atomic_t slow_ring_trc_cnt; #endif /* Fields used for heart beat. */ diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 860a52c090f..80a11218b9b 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -68,12 +68,6 @@ lpfc_drvr_version_show(struct class_device *cdev, char *buf) } static ssize_t -management_version_show(struct class_device *cdev, char *buf) -{ - return snprintf(buf, PAGE_SIZE, DFC_API_VERSION "\n"); -} - -static ssize_t lpfc_info_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); @@ -319,9 +313,8 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) if (cnt++ > 3000) { lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "%d:0466 Outstanding IO when " - "bringing Adapter offline\n", - phba->brd_no); + "0466 Outstanding IO when " + "bringing Adapter offline\n"); break; } } @@ -437,7 +430,7 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count) return -EIO; } -int +static int lpfc_get_hba_info(struct lpfc_hba *phba, uint32_t *mxri, uint32_t *axri, uint32_t *mrpi, uint32_t *arpi, @@ -694,9 +687,8 @@ lpfc_##attr##_init(struct lpfc_hba *phba, int val) \ return 0;\ }\ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \ - "%d:0449 lpfc_"#attr" attribute cannot be set to %d, "\ - "allowed range is ["#minval", "#maxval"]\n", \ - phba->brd_no, val); \ + "0449 lpfc_"#attr" attribute cannot be set to %d, "\ + "allowed range is ["#minval", "#maxval"]\n", val); \ phba->cfg_##attr = default;\ return -EINVAL;\ } @@ -710,9 +702,8 @@ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \ return 0;\ }\ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \ - "%d:0450 lpfc_"#attr" attribute cannot be set to %d, "\ - "allowed range is ["#minval", "#maxval"]\n", \ - phba->brd_no, val); \ + "0450 lpfc_"#attr" attribute cannot be set to %d, "\ + "allowed range is ["#minval", "#maxval"]\n", val); \ return -EINVAL;\ } @@ -734,6 +725,75 @@ lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \ return -EINVAL;\ } +#define lpfc_vport_param_show(attr) \ +static ssize_t \ +lpfc_##attr##_show(struct class_device *cdev, char *buf) \ +{ \ + struct Scsi_Host *shost = class_to_shost(cdev);\ + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ + int val = 0;\ + val = vport->cfg_##attr;\ + return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\ +} + +#define lpfc_vport_param_hex_show(attr) \ +static ssize_t \ +lpfc_##attr##_show(struct class_device *cdev, char *buf) \ +{ \ + struct Scsi_Host *shost = class_to_shost(cdev);\ + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ + int val = 0;\ + val = vport->cfg_##attr;\ + return snprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\ +} + +#define lpfc_vport_param_init(attr, default, minval, maxval) \ +static int \ +lpfc_##attr##_init(struct lpfc_vport *vport, int val) \ +{ \ + if (val >= minval && val <= maxval) {\ + vport->cfg_##attr = val;\ + return 0;\ + }\ + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \ + "0449 lpfc_"#attr" attribute cannot be set to %d, "\ + "allowed range is ["#minval", "#maxval"]\n", val); \ + vport->cfg_##attr = default;\ + return -EINVAL;\ +} + +#define lpfc_vport_param_set(attr, default, minval, maxval) \ +static int \ +lpfc_##attr##_set(struct lpfc_vport *vport, int val) \ +{ \ + if (val >= minval && val <= maxval) {\ + vport->cfg_##attr = val;\ + return 0;\ + }\ + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \ + "0450 lpfc_"#attr" attribute cannot be set to %d, "\ + "allowed range is ["#minval", "#maxval"]\n", val); \ + return -EINVAL;\ +} + +#define lpfc_vport_param_store(attr) \ +static ssize_t \ +lpfc_##attr##_store(struct class_device *cdev, const char *buf, size_t count) \ +{ \ + struct Scsi_Host *shost = class_to_shost(cdev);\ + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;\ + int val=0;\ + if (!isdigit(buf[0]))\ + return -EINVAL;\ + if (sscanf(buf, "%i", &val) != 1)\ + return -EINVAL;\ + if (lpfc_##attr##_set(vport, val) == 0) \ + return strlen(buf);\ + else \ + return -EINVAL;\ +} + + #define LPFC_ATTR(name, defval, minval, maxval, desc) \ static int lpfc_##name = defval;\ module_param(lpfc_##name, int, 0);\ @@ -778,6 +838,50 @@ lpfc_param_store(name)\ static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\ lpfc_##name##_show, lpfc_##name##_store) +#define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \ +static int lpfc_##name = defval;\ +module_param(lpfc_##name, int, 0);\ +MODULE_PARM_DESC(lpfc_##name, desc);\ +lpfc_vport_param_init(name, defval, minval, maxval) + +#define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \ +static int lpfc_##name = defval;\ +module_param(lpfc_##name, int, 0);\ +MODULE_PARM_DESC(lpfc_##name, desc);\ +lpfc_vport_param_show(name)\ +lpfc_vport_param_init(name, defval, minval, maxval)\ +static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) + +#define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \ +static int lpfc_##name = defval;\ +module_param(lpfc_##name, int, 0);\ +MODULE_PARM_DESC(lpfc_##name, desc);\ +lpfc_vport_param_show(name)\ +lpfc_vport_param_init(name, defval, minval, maxval)\ +lpfc_vport_param_set(name, defval, minval, maxval)\ +lpfc_vport_param_store(name)\ +static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\ + lpfc_##name##_show, lpfc_##name##_store) + +#define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \ +static int lpfc_##name = defval;\ +module_param(lpfc_##name, int, 0);\ +MODULE_PARM_DESC(lpfc_##name, desc);\ +lpfc_vport_param_hex_show(name)\ +lpfc_vport_param_init(name, defval, minval, maxval)\ +static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) + +#define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \ +static int lpfc_##name = defval;\ +module_param(lpfc_##name, int, 0);\ +MODULE_PARM_DESC(lpfc_##name, desc);\ +lpfc_vport_param_hex_show(name)\ +lpfc_vport_param_init(name, defval, minval, maxval)\ +lpfc_vport_param_set(name, defval, minval, maxval)\ +lpfc_vport_param_store(name)\ +static CLASS_DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\ + lpfc_##name##_show, lpfc_##name##_store) + static CLASS_DEVICE_ATTR(info, S_IRUGO, lpfc_info_show, NULL); static CLASS_DEVICE_ATTR(serialnum, S_IRUGO, lpfc_serialnum_show, NULL); static CLASS_DEVICE_ATTR(modeldesc, S_IRUGO, lpfc_modeldesc_show, NULL); @@ -794,8 +898,6 @@ static CLASS_DEVICE_ATTR(num_discovered_ports, S_IRUGO, static CLASS_DEVICE_ATTR(nport_evt_cnt, S_IRUGO, lpfc_nport_evt_cnt_show, NULL); static CLASS_DEVICE_ATTR(lpfc_drvr_version, S_IRUGO, lpfc_drvr_version_show, NULL); -static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show, - NULL); static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR, lpfc_board_mode_show, lpfc_board_mode_store); static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset); @@ -908,17 +1010,15 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); if (stat1) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0463 lpfc_soft_wwpn attribute set failed to reinit " - "adapter - %d\n", phba->brd_no, stat1); - + "0463 lpfc_soft_wwpn attribute set failed to " + "reinit adapter - %d\n", stat1); init_completion(&online_compl); lpfc_workq_post_event(phba, &stat2, &online_compl, LPFC_EVT_ONLINE); wait_for_completion(&online_compl); if (stat2) lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0464 lpfc_soft_wwpn attribute set failed to reinit " - "adapter - %d\n", phba->brd_no, stat2); - + "0464 lpfc_soft_wwpn attribute set failed to " + "reinit adapter - %d\n", stat2); return (stat1 || stat2) ? -EIO : count; } static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ @@ -927,8 +1027,8 @@ static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ static ssize_t lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) { - struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; + struct Scsi_Host *shost = class_to_shost(cdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; return snprintf(buf, PAGE_SIZE, "0x%llx\n", (unsigned long long)phba->cfg_soft_wwnn); } @@ -937,8 +1037,8 @@ lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) static ssize_t lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count) { - struct Scsi_Host *host = class_to_shost(cdev); - struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; + struct Scsi_Host *shost = class_to_shost(cdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; unsigned int i, j, cnt=count; u8 wwnn[8]; @@ -1002,7 +1102,7 @@ MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:" " 2 - select SLI-2 even on SLI-3 capable HBAs," " 3 - select SLI-3"); -LPFC_ATTR_R(npiv_enable, 0, 0, 1, "Enable NPIV functionality"); +LPFC_ATTR_R(enable_npiv, 0, 0, 1, "Enable NPIV functionality"); /* # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear @@ -1019,90 +1119,75 @@ lpfc_nodev_tmo_show(struct class_device *cdev, char *buf) { struct Scsi_Host *shost = class_to_shost(cdev); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; - struct lpfc_hba *phba = vport->phba; int val = 0; - val = phba->cfg_devloss_tmo; - return snprintf(buf, PAGE_SIZE, "%d\n", - phba->cfg_devloss_tmo); + val = vport->cfg_devloss_tmo; + return snprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_devloss_tmo); } static int -lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val) +lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val) { - static int warned; - if (phba->cfg_devloss_tmo != LPFC_DEF_DEVLOSS_TMO) { - phba->cfg_nodev_tmo = phba->cfg_devloss_tmo; - if (!warned && val != LPFC_DEF_DEVLOSS_TMO) { - warned = 1; - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0402 Ignoring nodev_tmo module " - "parameter because devloss_tmo is" - " set.\n", - phba->brd_no); - } + if (vport->cfg_devloss_tmo != LPFC_DEF_DEVLOSS_TMO) { + vport->cfg_nodev_tmo = vport->cfg_devloss_tmo; + if (val != LPFC_DEF_DEVLOSS_TMO) + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0402 Ignoring nodev_tmo module " + "parameter because devloss_tmo is " + "set.\n"); return 0; } if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { - phba->cfg_nodev_tmo = val; - phba->cfg_devloss_tmo = val; + vport->cfg_nodev_tmo = val; + vport->cfg_devloss_tmo = val; return 0; } - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0400 lpfc_nodev_tmo attribute cannot be set to %d, " - "allowed range is [%d, %d]\n", - phba->brd_no, val, - LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); - phba->cfg_nodev_tmo = LPFC_DEF_DEVLOSS_TMO; + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0400 lpfc_nodev_tmo attribute cannot be set to" + " %d, allowed range is [%d, %d]\n", + val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); + vport->cfg_nodev_tmo = LPFC_DEF_DEVLOSS_TMO; return -EINVAL; } static void -lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba) +lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) { - struct lpfc_vport *vport; struct Scsi_Host *shost; struct lpfc_nodelist *ndlp; - list_for_each_entry(vport, &phba->port_list, listentry) { - shost = lpfc_shost_from_vport(vport); - spin_lock_irq(shost->host_lock); - list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) - if (ndlp->rport) - ndlp->rport->dev_loss_tmo = - phba->cfg_devloss_tmo; - spin_unlock_irq(shost->host_lock); - } + shost = lpfc_shost_from_vport(vport); + spin_lock_irq(shost->host_lock); + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) + if (ndlp->rport) + ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo; + spin_unlock_irq(shost->host_lock); } static int -lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val) +lpfc_nodev_tmo_set(struct lpfc_vport *vport, int val) { - if (phba->dev_loss_tmo_changed || - (lpfc_devloss_tmo != LPFC_DEF_DEVLOSS_TMO)) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0401 Ignoring change to nodev_tmo " - "because devloss_tmo is set.\n", - phba->brd_no); + if (vport->dev_loss_tmo_changed || + (lpfc_devloss_tmo != LPFC_DEF_DEVLOSS_TMO)) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0401 Ignoring change to nodev_tmo " + "because devloss_tmo is set.\n"); return 0; } - if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { - phba->cfg_nodev_tmo = val; - phba->cfg_devloss_tmo = val; - lpfc_update_rport_devloss_tmo(phba); + vport->cfg_nodev_tmo = val; + vport->cfg_devloss_tmo = val; + lpfc_update_rport_devloss_tmo(vport); return 0; } - - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0403 lpfc_nodev_tmo attribute cannot be set to %d, " - "allowed range is [%d, %d]\n", - phba->brd_no, val, LPFC_MIN_DEVLOSS_TMO, - LPFC_MAX_DEVLOSS_TMO); + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0403 lpfc_nodev_tmo attribute cannot be set to" + "%d, allowed range is [%d, %d]\n", + val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); return -EINVAL; } -lpfc_param_store(nodev_tmo) +lpfc_vport_param_store(nodev_tmo) static CLASS_DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR, lpfc_nodev_tmo_show, lpfc_nodev_tmo_store); @@ -1116,29 +1201,28 @@ module_param(lpfc_devloss_tmo, int, 0); MODULE_PARM_DESC(lpfc_devloss_tmo, "Seconds driver will hold I/O waiting " "for a device to come back"); -lpfc_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO, - LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO) -lpfc_param_show(devloss_tmo) +lpfc_vport_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO, + LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO) +lpfc_vport_param_show(devloss_tmo) static int -lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val) +lpfc_devloss_tmo_set(struct lpfc_vport *vport, int val) { if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) { - phba->cfg_nodev_tmo = val; - phba->cfg_devloss_tmo = val; - phba->dev_loss_tmo_changed = 1; - lpfc_update_rport_devloss_tmo(phba); + vport->cfg_nodev_tmo = val; + vport->cfg_devloss_tmo = val; + vport->dev_loss_tmo_changed = 1; + lpfc_update_rport_devloss_tmo(vport); return 0; } - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0404 lpfc_devloss_tmo attribute cannot be set to" - " %d, allowed range is [%d, %d]\n", - phba->brd_no, val, LPFC_MIN_DEVLOSS_TMO, - LPFC_MAX_DEVLOSS_TMO); + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0404 lpfc_devloss_tmo attribute cannot be set to" + " %d, allowed range is [%d, %d]\n", + val, LPFC_MIN_DEVLOSS_TMO, LPFC_MAX_DEVLOSS_TMO); return -EINVAL; } -lpfc_param_store(devloss_tmo) +lpfc_vport_param_store(devloss_tmo) static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR, lpfc_devloss_tmo_show, lpfc_devloss_tmo_store); @@ -1160,14 +1244,15 @@ static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR, # LOG_LIBDFC 0x2000 LIBDFC events # LOG_ALL_MSG 0xffff LOG all messages */ -LPFC_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffff, "Verbose logging bit-mask"); +LPFC_VPORT_ATTR_HEX_RW(log_verbose, 0x0, 0x0, 0xffff, + "Verbose logging bit-mask"); /* # lun_queue_depth: This parameter is used to limit the number of outstanding # commands per FCP LUN. Value range is [1,128]. Default value is 30. */ -LPFC_ATTR_R(lun_queue_depth, 30, 1, 128, - "Max number of FCP commands we can queue to a specific LUN"); +LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 128, + "Max number of FCP commands we can queue to a specific LUN"); /* # hba_queue_depth: This parameter is used to limit the number of outstanding @@ -1188,12 +1273,12 @@ LPFC_ATTR_R(hba_queue_depth, 8192, 32, 8192, # are allowed to login to each other. # Default value of this parameter is 0. */ -LPFC_ATTR_R(peer_port_login, 0, 0, 1, - "Allow peer ports on the same physical port to login to each " - "other."); +LPFC_VPORT_ATTR_R(peer_port_login, 0, 0, 1, + "Allow peer ports on the same physical port to login to each " + "other."); /* -# vport_restrict_login: This parameter allows/prevents logins +# restrict_login: This parameter allows/prevents logins # between Virtual Ports and remote initiators. # When this parameter is not set (0) Virtual Ports will accept PLOGIs from # other initiators and will attempt to PLOGI all remote ports. @@ -1203,8 +1288,55 @@ LPFC_ATTR_R(peer_port_login, 0, 0, 1, # This parameter does not restrict logins to Fabric resident remote ports. # Default value of this parameter is 1. */ -LPFC_ATTR_RW(vport_restrict_login, 1, 0, 1, - "Restrict virtual ports login to remote initiators."); +static int lpfc_restrict_login = 1; +module_param(lpfc_restrict_login, int, 0); +MODULE_PARM_DESC(lpfc_restrict_login, + "Restrict virtual ports login to remote initiators."); +lpfc_vport_param_show(restrict_login); + +static int +lpfc_restrict_login_init(struct lpfc_vport *vport, int val) +{ + if (val < 0 || val > 1) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0449 lpfc_restrict_login attribute cannot " + "be set to %d, allowed range is [0, 1]\n", + val); + vport->cfg_restrict_login = 1; + return -EINVAL; + } + if (vport->port_type == LPFC_PHYSICAL_PORT) { + vport->cfg_restrict_login = 0; + return 0; + } + vport->cfg_restrict_login = val; + return 0; +} + +static int +lpfc_restrict_login_set(struct lpfc_vport *vport, int val) +{ + if (val < 0 || val > 1) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0450 lpfc_restrict_login attribute cannot " + "be set to %d, allowed range is [0, 1]\n", + val); + vport->cfg_restrict_login = 1; + return -EINVAL; + } + if (vport->port_type == LPFC_PHYSICAL_PORT && val != 0) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0468 lpfc_restrict_login must be 0 for " + "Physical ports.\n"); + vport->cfg_restrict_login = 0; + return 0; + } + vport->cfg_restrict_login = val; + return 0; +} +lpfc_vport_param_store(restrict_login); +static CLASS_DEVICE_ATTR(lpfc_restrict_login, S_IRUGO | S_IWUSR, + lpfc_restrict_login_show, lpfc_restrict_login_store); /* # Some disk devices have a "select ID" or "select Target" capability. @@ -1223,8 +1355,8 @@ LPFC_ATTR_RW(vport_restrict_login, 1, 0, 1, # and will not work across a fabric. Also this parameter will take # effect only in the case when ALPA map is not available.) */ -LPFC_ATTR_R(scan_down, 1, 0, 1, - "Start scanning for devices from highest ALPA to lowest"); +LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1, + "Start scanning for devices from highest ALPA to lowest"); /* # lpfc_topology: link topology for init link @@ -1255,15 +1387,15 @@ LPFC_ATTR_R(link_speed, 0, 0, 8, "Select link speed"); # lpfc_fcp_class: Determines FC class to use for the FCP protocol. # Value range is [2,3]. Default value is 3. */ -LPFC_ATTR_R(fcp_class, 3, 2, 3, - "Select Fibre Channel class of service for FCP sequences"); +LPFC_VPORT_ATTR_R(fcp_class, 3, 2, 3, + "Select Fibre Channel class of service for FCP sequences"); /* # lpfc_use_adisc: Use ADISC for FCP rediscovery instead of PLOGI. Value range # is [0,1]. Default value is 0. */ -LPFC_ATTR_RW(use_adisc, 0, 0, 1, - "Use ADISC on rediscovery to authenticate FCP devices"); +LPFC_VPORT_ATTR_RW(use_adisc, 0, 0, 1, + "Use ADISC on rediscovery to authenticate FCP devices"); /* # lpfc_ack0: Use ACK0, instead of ACK1 for class 2 acknowledgement. Value @@ -1315,13 +1447,13 @@ LPFC_ATTR_R(multi_ring_type, FC_LLC_SNAP, 1, # 2 = support FDMI with attribute of hostname # Value range [0,2]. Default value is 0. */ -LPFC_ATTR_RW(fdmi_on, 0, 0, 2, "Enable FDMI support"); +LPFC_VPORT_ATTR_RW(fdmi_on, 0, 0, 2, "Enable FDMI support"); /* # Specifies the maximum number of ELS cmds we can have outstanding (for # discovery). Value range is [1,64]. Default value = 32. */ -LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands " +LPFC_VPORT_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands " "during discovery"); /* @@ -1329,8 +1461,7 @@ LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands " # Value range is [0,65535]. Default value is 255. # NOTE: The SCSI layer might probe all allowed LUN on some old targets. */ -LPFC_ATTR_R(max_luns, 255, 0, 65535, - "Maximum allowed LUN"); +LPFC_VPORT_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN"); /* # lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring. @@ -1367,7 +1498,6 @@ struct class_device_attribute *lpfc_hba_attrs[] = { &class_device_attr_lpfc_lun_queue_depth, &class_device_attr_lpfc_hba_queue_depth, &class_device_attr_lpfc_peer_port_login, - &class_device_attr_lpfc_vport_restrict_login, &class_device_attr_lpfc_nodev_tmo, &class_device_attr_lpfc_devloss_tmo, &class_device_attr_lpfc_fcp_class, @@ -1383,9 +1513,8 @@ struct class_device_attribute *lpfc_hba_attrs[] = { &class_device_attr_lpfc_multi_ring_type, &class_device_attr_lpfc_fdmi_on, &class_device_attr_lpfc_max_luns, - &class_device_attr_lpfc_npiv_enable, + &class_device_attr_lpfc_enable_npiv, &class_device_attr_nport_evt_cnt, - &class_device_attr_management_version, &class_device_attr_board_mode, &class_device_attr_max_vpi, &class_device_attr_used_vpi, @@ -1404,6 +1533,28 @@ struct class_device_attribute *lpfc_hba_attrs[] = { NULL, }; +struct class_device_attribute *lpfc_vport_attrs[] = { + &class_device_attr_info, + &class_device_attr_state, + &class_device_attr_num_discovered_ports, + &class_device_attr_lpfc_drvr_version, + + &class_device_attr_lpfc_log_verbose, + &class_device_attr_lpfc_lun_queue_depth, + &class_device_attr_lpfc_nodev_tmo, + &class_device_attr_lpfc_devloss_tmo, + &class_device_attr_lpfc_hba_queue_depth, + &class_device_attr_lpfc_peer_port_login, + &class_device_attr_lpfc_restrict_login, + &class_device_attr_lpfc_fcp_class, + &class_device_attr_lpfc_use_adisc, + &class_device_attr_lpfc_fdmi_on, + &class_device_attr_lpfc_max_luns, + &class_device_attr_nport_evt_cnt, + &class_device_attr_npiv_info, + NULL, +}; + static ssize_t sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) @@ -2243,7 +2394,6 @@ struct fc_function_template lpfc_vport_transport_functions = { .get_starget_port_name = lpfc_get_starget_port_name, .show_starget_port_name = 1, - .issue_fc_host_lip = lpfc_issue_lip, .dev_loss_tmo_callbk = lpfc_dev_loss_tmo_callbk, .terminate_rport_io = lpfc_terminate_rport_io, @@ -2253,39 +2403,25 @@ struct fc_function_template lpfc_vport_transport_functions = { void lpfc_get_cfgparam(struct lpfc_hba *phba) { - lpfc_log_verbose_init(phba, lpfc_log_verbose); lpfc_cr_delay_init(phba, lpfc_cr_delay); lpfc_cr_count_init(phba, lpfc_cr_count); lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support); lpfc_multi_ring_rctl_init(phba, lpfc_multi_ring_rctl); lpfc_multi_ring_type_init(phba, lpfc_multi_ring_type); - lpfc_lun_queue_depth_init(phba, lpfc_lun_queue_depth); - lpfc_fcp_class_init(phba, lpfc_fcp_class); - lpfc_use_adisc_init(phba, lpfc_use_adisc); lpfc_ack0_init(phba, lpfc_ack0); lpfc_topology_init(phba, lpfc_topology); - lpfc_scan_down_init(phba, lpfc_scan_down); lpfc_link_speed_init(phba, lpfc_link_speed); - lpfc_fdmi_on_init(phba, lpfc_fdmi_on); - lpfc_discovery_threads_init(phba, lpfc_discovery_threads); - lpfc_max_luns_init(phba, lpfc_max_luns); lpfc_poll_tmo_init(phba, lpfc_poll_tmo); - lpfc_peer_port_login_init(phba, lpfc_peer_port_login); - lpfc_npiv_enable_init(phba, lpfc_npiv_enable); - lpfc_vport_restrict_login_init(phba, lpfc_vport_restrict_login); + lpfc_enable_npiv_init(phba, lpfc_enable_npiv); lpfc_use_msi_init(phba, lpfc_use_msi); - lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo); - lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo); phba->cfg_poll = lpfc_poll; phba->cfg_soft_wwnn = 0L; phba->cfg_soft_wwpn = 0L; - /* * The total number of segments is the configuration value plus 2 * since the IOCB need a command and response bde. */ phba->cfg_sg_seg_cnt = LPFC_SG_SEG_CNT + 2; - /* * Since the sg_tablesize is module parameter, the sg_dma_buf_size * used to create the sg_dma_buf_pool must be dynamically calculated @@ -2293,9 +2429,24 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) + (phba->cfg_sg_seg_cnt * sizeof(struct ulp_bde64)); - - lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); + return; +} +void +lpfc_get_vport_cfgparam(struct lpfc_vport *vport) +{ + lpfc_log_verbose_init(vport, lpfc_log_verbose); + lpfc_lun_queue_depth_init(vport, lpfc_lun_queue_depth); + lpfc_devloss_tmo_init(vport, lpfc_devloss_tmo); + lpfc_nodev_tmo_init(vport, lpfc_nodev_tmo); + lpfc_peer_port_login_init(vport, lpfc_peer_port_login); + lpfc_restrict_login_init(vport, lpfc_restrict_login); + lpfc_fcp_class_init(vport, lpfc_fcp_class); + lpfc_use_adisc_init(vport, lpfc_use_adisc); + lpfc_fdmi_on_init(vport, lpfc_fdmi_on); + lpfc_discovery_threads_init(vport, lpfc_discovery_threads); + lpfc_max_luns_init(vport, lpfc_max_luns); + lpfc_scan_down_init(vport, lpfc_scan_down); return; } diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index e19d1a74658..a599e151071 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -40,6 +40,7 @@ void lpfc_reg_vpi(struct lpfc_hba *, uint16_t, uint32_t, LPFC_MBOXQ_t *); void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *); void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t); +struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t); void lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove); int lpfc_linkdown(struct lpfc_hba *); void lpfc_mbx_cmpl_read_la(struct lpfc_hba *, LPFC_MBOXQ_t *); @@ -101,7 +102,7 @@ int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t); int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *); int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, - struct lpfc_nodelist *, LPFC_MBOXQ_t *, uint8_t); + struct lpfc_nodelist *, LPFC_MBOXQ_t *); int lpfc_els_rsp_reject(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *, struct lpfc_nodelist *, LPFC_MBOXQ_t *); int lpfc_els_rsp_adisc_acc(struct lpfc_vport *, struct lpfc_iocbq *, @@ -117,6 +118,7 @@ void lpfc_els_unsol_event(struct lpfc_hba *, struct lpfc_sli_ring *, int lpfc_els_handle_rscn(struct lpfc_vport *); void lpfc_els_flush_rscn(struct lpfc_vport *); int lpfc_rscn_payload_check(struct lpfc_vport *, uint32_t); +void lpfc_els_flush_all_cmd(struct lpfc_hba *); void lpfc_els_flush_cmd(struct lpfc_vport *); int lpfc_els_disc_adisc(struct lpfc_vport *); int lpfc_els_disc_plogi(struct lpfc_vport *); @@ -161,9 +163,11 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); void lpfc_mbox_cmpl_put(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_mbox_tmo_val(struct lpfc_hba *, int); -void lpfc_config_hbq(struct lpfc_hba *, struct lpfc_hbq_init *, uint32_t , - LPFC_MBOXQ_t *); +void lpfc_config_hbq(struct lpfc_hba *, uint32_t, struct lpfc_hbq_init *, + uint32_t , LPFC_MBOXQ_t *); struct lpfc_hbq_entry * lpfc_sli_next_hbq_slot(struct lpfc_hba *, uint32_t); +struct hbq_dmabuf *lpfc_els_hbq_alloc(struct lpfc_hba *); +void lpfc_els_hbq_free(struct lpfc_hba *, struct hbq_dmabuf *); int lpfc_mem_alloc(struct lpfc_hba *); void lpfc_mem_free(struct lpfc_hba *); @@ -200,6 +204,7 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *, struct lpfc_sli_ring *, dma_addr_t); +int lpfc_sli_hbq_count(void); int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *, uint32_t); int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t); void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *); @@ -207,10 +212,9 @@ struct hbq_dmabuf *lpfc_sli_hbqbuf_find(struct lpfc_hba *, uint32_t); int lpfc_sli_hbq_size(void); int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *, struct lpfc_iocbq *); -int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, - uint64_t, lpfc_ctx_cmd); -int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t, - uint64_t, uint32_t, lpfc_ctx_cmd); +int lpfc_sli_sum_iocb(struct lpfc_vport *, uint16_t, uint64_t, lpfc_ctx_cmd); +int lpfc_sli_abort_iocb(struct lpfc_vport *, struct lpfc_sli_ring *, uint16_t, + uint64_t, lpfc_ctx_cmd); void lpfc_mbox_timeout(unsigned long); void lpfc_mbox_timeout_handler(struct lpfc_hba *); @@ -234,8 +238,6 @@ void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb); -void *lpfc_hbq_alloc(struct lpfc_hba *, int, dma_addr_t *); -void lpfc_hbq_free(struct lpfc_hba *, void *, dma_addr_t); void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *); void *lpfc_mbuf_alloc(struct lpfc_hba *, int, dma_addr_t *); @@ -248,10 +250,13 @@ const char* lpfc_info(struct Scsi_Host *); int lpfc_scan_finished(struct Scsi_Host *, unsigned long); void lpfc_get_cfgparam(struct lpfc_hba *); +void lpfc_get_vport_cfgparam(struct lpfc_vport *); int lpfc_alloc_sysfs_attr(struct lpfc_vport *); void lpfc_free_sysfs_attr(struct lpfc_vport *); extern struct class_device_attribute *lpfc_hba_attrs[]; +extern struct class_device_attribute *lpfc_vport_attrs[]; extern struct scsi_host_template lpfc_template; +extern struct scsi_host_template lpfc_vport_template; extern struct fc_function_template lpfc_transport_functions; extern struct fc_function_template lpfc_vport_transport_functions; extern int lpfc_sli_mode; @@ -260,7 +265,7 @@ int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t); void lpfc_terminate_rport_io(struct fc_rport *); void lpfc_dev_loss_tmo_callbk(struct fc_rport *rport); -struct lpfc_vport *lpfc_create_port(struct lpfc_hba *, int, struct fc_vport *); +struct lpfc_vport *lpfc_create_port(struct lpfc_hba *, int, struct device *); int lpfc_vport_disable(struct fc_vport *fc_vport, bool disable); void lpfc_mbx_unreg_vpi(struct lpfc_vport *); void destroy_port(struct lpfc_vport *); @@ -271,6 +276,9 @@ extern void lpfc_debugfs_initialize(struct lpfc_vport *); extern void lpfc_debugfs_terminate(struct lpfc_vport *); extern void lpfc_debugfs_disc_trc(struct lpfc_vport *, int, char *, uint32_t, uint32_t, uint32_t); +extern void lpfc_debugfs_slow_ring_trc(struct lpfc_hba *, char *, uint32_t, + uint32_t, uint32_t); +extern struct lpfc_hbq_init *lpfc_hbq_defs[]; /* Interface exported by fabric iocb scheduler */ int lpfc_issue_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index ae9d6f385a6..c701e4d611a 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -257,6 +257,10 @@ lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) { struct lpfc_dmabuf *buf_ptr; + if (ctiocb->context_un.ndlp) { + lpfc_nlp_put(ctiocb->context_un.ndlp); + ctiocb->context_un.ndlp = NULL; + } if (ctiocb->context1) { buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1; lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); @@ -314,6 +318,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, /* Save for completion so we can release these resources */ geniocb->context1 = (uint8_t *) inp; geniocb->context2 = (uint8_t *) outp; + geniocb->context_un.ndlp = ndlp; /* Fill in payload, bp points to frame payload */ icmd->ulpCommand = CMD_GEN_REQUEST64_CR; @@ -341,11 +346,11 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, } /* Issue GEN REQ IOCB for NPORT <did> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0119 Issue GEN REQ IOCB to NPORT x%x " - "Data: x%x x%x\n", phba->brd_no, vport->vpi, - ndlp->nlp_DID, icmd->ulpIoTag, - vport->port_state); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0119 Issue GEN REQ IOCB to NPORT x%x " + "Data: x%x x%x\n", + ndlp->nlp_DID, icmd->ulpIoTag, + vport->port_state); geniocb->iocb_cmpl = cmpl; geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; geniocb->vport = vport; @@ -390,17 +395,19 @@ lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp, return 0; } -static struct lpfc_vport * +struct lpfc_vport * lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) { - struct lpfc_vport *vport_curr; + unsigned long flags; + spin_lock_irqsave(&phba->hbalock, flags); list_for_each_entry(vport_curr, &phba->port_list, listentry) { - if ((vport_curr->fc_myDID) && - (vport_curr->fc_myDID == did)) + if ((vport_curr->fc_myDID) && (vport_curr->fc_myDID == did)) { + spin_unlock_irqrestore(&phba->hbalock, flags); return vport_curr; + } } - + spin_unlock_irqrestore(&phba->hbalock, flags); return NULL; } @@ -449,10 +456,10 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) */ if ((Did != vport->fc_myDID) && ((lpfc_find_vport_by_did(phba, Did) == NULL) || - phba->cfg_peer_port_login)) { + vport->cfg_peer_port_login)) { if ((vport->port_type != LPFC_NPIV_PORT) || (vport->fc_flag & FC_RFF_NOT_SUPPORTED) || - (!phba->cfg_vport_restrict_login)) { + (!vport->cfg_restrict_login)) { ndlp = lpfc_setup_disc_node(vport, Did); if (ndlp) { lpfc_debugfs_disc_trc(vport, @@ -462,14 +469,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) Did, ndlp->nlp_flag, vport->fc_flag); - lpfc_printf_log(phba, KERN_INFO, + lpfc_printf_vlog(vport, + KERN_INFO, LOG_DISCOVERY, - "%d (%d):0238 Process " + "0238 Process " "x%x NameServer Rsp" "Data: x%x x%x x%x\n", - phba->brd_no, - vport->vpi, Did, - ndlp->nlp_flag, + Did, ndlp->nlp_flag, vport->fc_flag, vport->fc_rscn_id_cnt); } else { @@ -480,14 +486,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) Did, vport->fc_flag, vport->fc_rscn_id_cnt); - lpfc_printf_log(phba, KERN_INFO, + lpfc_printf_vlog(vport, + KERN_INFO, LOG_DISCOVERY, - "%d (%d):0239 Skip x%x " + "0239 Skip x%x " "NameServer Rsp Data: " "x%x x%x\n", - phba->brd_no, - vport->vpi, Did, - vport->fc_flag, + Did, vport->fc_flag, vport->fc_rscn_id_cnt); } @@ -514,14 +519,13 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) Did, vport->fc_flag, vport->fc_rscn_id_cnt); - lpfc_printf_log(phba, KERN_INFO, + lpfc_printf_vlog(vport, + KERN_INFO, LOG_DISCOVERY, - "%d (%d):0245 Skip x%x " + "0245 Skip x%x " "NameServer Rsp Data: " "x%x x%x\n", - phba->brd_no, - vport->vpi, Did, - vport->fc_flag, + Did, vport->fc_flag, vport->fc_rscn_id_cnt); } } @@ -549,8 +553,12 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *bmp; struct lpfc_dmabuf *outp; struct lpfc_sli_ct_request *CTrsp; + struct lpfc_nodelist *ndlp; int rc; + /* First save ndlp, before we overwrite it */ + ndlp = cmdiocb->context_un.ndlp; + /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; @@ -568,9 +576,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) { - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0216 Link event during NS query\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0216 Link event during NS query\n"); lpfc_vport_set_state(vport, FC_VPORT_FAILED); goto out; } @@ -588,46 +595,61 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; } lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n", - phba->brd_no, vport->vpi, irsp->ulpStatus, - vport->fc_ns_retry); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0257 GID_FT Query error: 0x%x 0x%x\n", + irsp->ulpStatus, vport->fc_ns_retry); } else { /* Good status, continue checking */ CTrsp = (struct lpfc_sli_ct_request *) outp->virt; if (CTrsp->CommandResponse.bits.CmdRsp == be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0208 NameServer Rsp " - "Data: x%x\n", - phba->brd_no, vport->vpi, - vport->fc_flag); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0208 NameServer Rsp Data: x%x\n", + vport->fc_flag); lpfc_ns_rsp(vport, outp, (uint32_t) (irsp->un.genreq64.bdl.bdeSize)); } else if (CTrsp->CommandResponse.bits.CmdRsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { /* NameServer Rsp Error */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0240 NameServer Rsp Error " + if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ) + && (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) { + lpfc_printf_vlog(vport, KERN_INFO, + LOG_DISCOVERY, + "0269 No NameServer Entries " "Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, CTrsp->CommandResponse.bits.CmdRsp, (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, vport->fc_flag); - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, + "GID_FT no entry cmd:x%x rsn:x%x exp:x%x", + (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, + (uint32_t) CTrsp->ReasonCode, + (uint32_t) CTrsp->Explanation); + } else { + lpfc_printf_vlog(vport, KERN_INFO, + LOG_DISCOVERY, + "0240 NameServer Rsp Error " + "Data: x%x x%x x%x x%x\n", + CTrsp->CommandResponse.bits.CmdRsp, + (uint32_t) CTrsp->ReasonCode, + (uint32_t) CTrsp->Explanation, + vport->fc_flag); + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x", (uint32_t)CTrsp->CommandResponse.bits.CmdRsp, (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation); + } + } else { /* NameServer Rsp Error */ - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0241 NameServer Rsp Error " + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0241 NameServer Rsp Error " "Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, CTrsp->CommandResponse.bits.CmdRsp, (uint32_t) CTrsp->ReasonCode, (uint32_t) CTrsp->Explanation, @@ -661,11 +683,12 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_disc_start(vport); } out: + cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */ lpfc_ct_free_iocb(phba, cmdiocb); return; } -void +static void lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { @@ -695,40 +718,37 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { if ((fbits & FC4_FEATURE_INIT) && !(fbits & FC4_FEATURE_TARGET)) { - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0245 Skip x%x GFF " - "NameServer Rsp Data: (init) " - "x%x x%x\n", phba->brd_no, - vport->vpi, did, fbits, - vport->fc_rscn_id_cnt); + lpfc_printf_vlog(vport, KERN_INFO, + LOG_DISCOVERY, + "0270 Skip x%x GFF " + "NameServer Rsp Data: (init) " + "x%x x%x\n", did, fbits, + vport->fc_rscn_id_cnt); goto out; } } } else { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0267 NameServer GFF Rsp" - " x%x Error (%d %d) Data: x%x x%x\n", - phba->brd_no, vport->vpi, did, - irsp->ulpStatus, irsp->un.ulpWord[4], - vport->fc_flag, vport->fc_rscn_id_cnt) + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0267 NameServer GFF Rsp " + "x%x Error (%d %d) Data: x%x x%x\n", + did, irsp->ulpStatus, irsp->un.ulpWord[4], + vport->fc_flag, vport->fc_rscn_id_cnt) } /* This is a target port, unregistered port, or the GFF_ID failed */ ndlp = lpfc_setup_disc_node(vport, did); if (ndlp) { - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0242 Process x%x GFF " - "NameServer Rsp Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, - did, ndlp->nlp_flag, vport->fc_flag, - vport->fc_rscn_id_cnt); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0242 Process x%x GFF " + "NameServer Rsp Data: x%x x%x x%x\n", + did, ndlp->nlp_flag, vport->fc_flag, + vport->fc_rscn_id_cnt); } else { - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0243 Skip x%x GFF " - "NameServer Rsp Data: x%x x%x\n", - phba->brd_no, vport->vpi, did, - vport->fc_flag, vport->fc_rscn_id_cnt); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0243 Skip x%x GFF " + "NameServer Rsp Data: x%x x%x\n", did, + vport->fc_flag, vport->fc_rscn_id_cnt); } out: /* Link up / RSCN discovery */ @@ -766,10 +786,14 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *outp; IOCB_t *irsp; struct lpfc_sli_ct_request *CTrsp; + struct lpfc_nodelist *ndlp; int cmdcode, rc; uint8_t retry; uint32_t latt; + /* First save ndlp, before we overwrite it */ + ndlp = cmdiocb->context_un.ndlp; + /* we pass cmdiocb to state machine which needs rspiocb as well */ cmdiocb->context_un.rsp_iocb = rspiocb; @@ -784,22 +808,21 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, latt = lpfc_els_chk_latt(vport); /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0209 RFT request completes, latt %d, " - "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n", - phba->brd_no, vport->vpi, latt, irsp->ulpStatus, - CTrsp->CommandResponse.bits.CmdRsp, - cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0209 RFT request completes, latt %d, " + "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n", + latt, irsp->ulpStatus, + CTrsp->CommandResponse.bits.CmdRsp, + cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "CT cmd cmpl: status:x%x/x%x cmd:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode); if (irsp->ulpStatus) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0268 NS cmd %x Error (%d %d)\n", - phba->brd_no, vport->vpi, cmdcode, - irsp->ulpStatus, irsp->un.ulpWord[4]); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0268 NS cmd %x Error (%d %d)\n", + cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4]); if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || @@ -811,15 +834,15 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; retry++; - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0216 Retrying NS cmd %x\n", - phba->brd_no, vport->vpi, cmdcode); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0216 Retrying NS cmd %x\n", cmdcode); rc = lpfc_ns_cmd(vport, cmdcode, retry, 0); if (rc == 0) goto out; } out: + cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */ lpfc_ct_free_iocb(phba, cmdiocb); return; } @@ -862,7 +885,7 @@ lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, return; } -int +static int lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol, size_t size) { @@ -957,10 +980,9 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, } /* NameServer Req */ - lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY, - "%d (%d):0236 NameServer Req Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, cmdcode, vport->fc_flag, - vport->fc_rscn_id_cnt); + lpfc_printf_vlog(vport, KERN_INFO ,LOG_DISCOVERY, + "0236 NameServer Req Data: x%x x%x x%x\n", + cmdcode, vport->fc_flag, vport->fc_rscn_id_cnt); bpl = (struct ulp_bde64 *) bmp->virt; memset(bpl, 0, sizeof(struct ulp_bde64)); @@ -1059,6 +1081,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, cmpl = lpfc_cmpl_ct_cmd_rff_id; break; } + lpfc_nlp_get(ndlp); if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) { /* On success, The cmpl function will free the buffers */ @@ -1069,6 +1092,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, } rc=6; + lpfc_nlp_put(ndlp); lpfc_mbuf_free(phba, bmp->virt, bmp->phys); ns_cmd_free_bmp: kfree(bmp); @@ -1077,10 +1101,9 @@ ns_cmd_free_mpvirt: ns_cmd_free_mp: kfree(mp); ns_cmd_exit: - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0266 Issue NameServer Req x%x err %d Data: x%x x%x\n", - phba->brd_no, vport->vpi, cmdcode, rc, vport->fc_flag, - vport->fc_rscn_id_cnt); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0266 Issue NameServer Req x%x err %d Data: x%x x%x\n", + cmdcode, rc, vport->fc_flag, vport->fc_rscn_id_cnt); return 1; } @@ -1106,12 +1129,11 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp->ulpStatus, irsp->un.ulpWord[4], latt); if (latt || irsp->ulpStatus) { - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0229 FDMI cmd %04x failed, latt = %d " - "ulpStatus: x%x, rid x%x\n", - phba->brd_no, vport->vpi, - be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus, - irsp->un.ulpWord[4]); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0229 FDMI cmd %04x failed, latt = %d " + "ulpStatus: x%x, rid x%x\n", + be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus, + irsp->un.ulpWord[4]); lpfc_ct_free_iocb(phba, cmdiocb); return; } @@ -1119,10 +1141,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp = lpfc_findnode_did(vport, FDMI_DID); if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { /* FDMI rsp failed */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0220 FDMI rsp failed Data: x%x\n", - phba->brd_no, vport->vpi, - be16_to_cpu(fdmi_cmd)); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0220 FDMI rsp failed Data: x%x\n", + be16_to_cpu(fdmi_cmd)); } switch (be16_to_cpu(fdmi_cmd)) { @@ -1185,11 +1206,9 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) INIT_LIST_HEAD(&bmp->list); /* FDMI request */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0218 FDMI Request Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, vport->fc_flag, - vport->port_state, cmdcode); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0218 FDMI Request Data: x%x x%x x%x\n", + vport->fc_flag, vport->port_state, cmdcode); CtReq = (struct lpfc_sli_ct_request *) mp->virt; memset(CtReq, 0, sizeof(struct lpfc_sli_ct_request)); @@ -1449,7 +1468,7 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) pab->ab.EntryCnt++; size += FOURBYTES + len; - if (phba->cfg_fdmi_on == 2) { + if (vport->cfg_fdmi_on == 2) { /* #6 Port attribute entry */ ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size); @@ -1499,10 +1518,12 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) bpl->tus.w = le32_to_cpu(bpl->tus.w); cmpl = lpfc_cmpl_ct_cmd_fdmi; + lpfc_nlp_get(ndlp); if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0)) return 0; + lpfc_nlp_put(ndlp); lpfc_mbuf_free(phba, bmp->virt, bmp->phys); fdmi_cmd_free_bmp: kfree(bmp); @@ -1512,9 +1533,9 @@ fdmi_cmd_free_mp: kfree(mp); fdmi_cmd_exit: /* Issue FDMI request failed */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0244 Issue FDMI request failed Data: x%x\n", - phba->brd_no, vport->vpi, cmdcode); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0244 Issue FDMI request failed Data: x%x\n", + cmdcode); return 1; } diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 673cfe11cc2..2e3c01bebed 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -71,15 +71,22 @@ * lpfc_debugfs_mask_disc_trc=Y Where Y is an event mask as defined in * lpfc_debugfs.h . */ -static int lpfc_debugfs_enable = 0; +static int lpfc_debugfs_enable = 1; module_param(lpfc_debugfs_enable, int, 0); MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services"); -static int lpfc_debugfs_max_disc_trc = 0; /* This MUST be a power of 2 */ +/* This MUST be a power of 2 */ +static int lpfc_debugfs_max_disc_trc = 0; module_param(lpfc_debugfs_max_disc_trc, int, 0); MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc, "Set debugfs discovery trace depth"); +/* This MUST be a power of 2 */ +static int lpfc_debugfs_max_slow_ring_trc = 0; +module_param(lpfc_debugfs_max_slow_ring_trc, int, 0); +MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc, + "Set debugfs slow ring trace depth"); + static int lpfc_debugfs_mask_disc_trc = 0; module_param(lpfc_debugfs_mask_disc_trc, int, 0); MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, @@ -87,28 +94,34 @@ MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, #include <linux/debugfs.h> -/* size of discovery_trace output line */ -#define LPFC_DISC_TRC_ENTRY_SIZE 80 +/* size of output line, for discovery_trace and slow_ring_trace */ +#define LPFC_DEBUG_TRC_ENTRY_SIZE 100 /* nodelist output buffer size */ #define LPFC_NODELIST_SIZE 8192 #define LPFC_NODELIST_ENTRY_SIZE 120 +/* dumpslim output buffer size */ +#define LPFC_DUMPSLIM_SIZE 4096 + +/* hbqinfo output buffer size */ +#define LPFC_HBQINFO_SIZE 8192 + struct lpfc_debug { char *buffer; int len; }; -atomic_t lpfc_debugfs_disc_trc_cnt = ATOMIC_INIT(0); -unsigned long lpfc_debugfs_start_time = 0L; +static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); +static unsigned long lpfc_debugfs_start_time = 0L; static int lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) { int i, index, len, enable; uint32_t ms; - struct lpfc_disc_trc *dtp; - char buffer[80]; + struct lpfc_debugfs_trc *dtp; + char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE]; enable = lpfc_debugfs_enable; @@ -122,7 +135,8 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) if (!dtp->fmt) continue; ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); - snprintf(buffer, 80, "%010d:%010d ms:%s\n", + snprintf(buffer, + LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", dtp->seq_cnt, ms, dtp->fmt); len += snprintf(buf+len, size-len, buffer, dtp->data1, dtp->data2, dtp->data3); @@ -132,7 +146,8 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) if (!dtp->fmt) continue; ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); - snprintf(buffer, 80, "%010d:%010d ms:%s\n", + snprintf(buffer, + LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", dtp->seq_cnt, ms, dtp->fmt); len += snprintf(buf+len, size-len, buffer, dtp->data1, dtp->data2, dtp->data3); @@ -143,6 +158,236 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) } static int +lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) +{ + int i, index, len, enable; + uint32_t ms; + struct lpfc_debugfs_trc *dtp; + char buffer[LPFC_DEBUG_TRC_ENTRY_SIZE]; + + + enable = lpfc_debugfs_enable; + lpfc_debugfs_enable = 0; + + len = 0; + index = (atomic_read(&phba->slow_ring_trc_cnt) + 1) & + (lpfc_debugfs_max_slow_ring_trc - 1); + for (i = index; i < lpfc_debugfs_max_slow_ring_trc; i++) { + dtp = phba->slow_ring_trc + i; + if (!dtp->fmt) + continue; + ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); + snprintf(buffer, + LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", + dtp->seq_cnt, ms, dtp->fmt); + len += snprintf(buf+len, size-len, buffer, + dtp->data1, dtp->data2, dtp->data3); + } + for (i = 0; i < index; i++) { + dtp = phba->slow_ring_trc + i; + if (!dtp->fmt) + continue; + ms = jiffies_to_msecs(dtp->jif - lpfc_debugfs_start_time); + snprintf(buffer, + LPFC_DEBUG_TRC_ENTRY_SIZE, "%010d:%010d ms:%s\n", + dtp->seq_cnt, ms, dtp->fmt); + len += snprintf(buf+len, size-len, buffer, + dtp->data1, dtp->data2, dtp->data3); + } + + lpfc_debugfs_enable = enable; + return len; +} + +static int lpfc_debugfs_last_hbq = -1; + +static int +lpfc_debugfs_hbqinfo_data(struct lpfc_hba *phba, char *buf, int size) +{ + int len = 0; + int cnt, i, j, found, posted, low; + uint32_t phys, raw_index, getidx; + struct lpfc_hbq_init *hip; + struct hbq_s *hbqs; + struct lpfc_hbq_entry *hbqe; + struct lpfc_dmabuf *d_buf; + struct hbq_dmabuf *hbq_buf; + + cnt = LPFC_HBQINFO_SIZE; + spin_lock_irq(&phba->hbalock); + + /* toggle between multiple hbqs, if any */ + i = lpfc_sli_hbq_count(); + if (i > 1) { + lpfc_debugfs_last_hbq++; + if (lpfc_debugfs_last_hbq >= i) + lpfc_debugfs_last_hbq = 0; + } + else + lpfc_debugfs_last_hbq = 0; + + i = lpfc_debugfs_last_hbq; + + len += snprintf(buf+len, size-len, "HBQ %d Info\n", i); + + hbqs = &phba->hbqs[i]; + posted = 0; + list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) + posted++; + + hip = lpfc_hbq_defs[i]; + len += snprintf(buf+len, size-len, + "idx:%d prof:%d rn:%d bufcnt:%d icnt:%d acnt:%d posted %d\n", + hip->hbq_index, hip->profile, hip->rn, + hip->buffer_count, hip->init_count, hip->add_count, posted); + + raw_index = phba->hbq_get[i]; + getidx = le32_to_cpu(raw_index); + len += snprintf(buf+len, size-len, + "entrys:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n", + hbqs->entry_count, hbqs->hbqPutIdx, hbqs->next_hbqPutIdx, + hbqs->local_hbqGetIdx, getidx); + + hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt; + for (j=0; j<hbqs->entry_count; j++) { + len += snprintf(buf+len, size-len, + "%03d: %08x %04x %05x ", j, + hbqe->bde.addrLow, hbqe->bde.tus.w, hbqe->buffer_tag); + + i = 0; + found = 0; + + /* First calculate if slot has an associated posted buffer */ + low = hbqs->hbqPutIdx - posted; + if (low >= 0) { + if ((j >= hbqs->hbqPutIdx) || (j < low)) { + len += snprintf(buf+len, size-len, "Unused\n"); + goto skipit; + } + } + else { + if ((j >= hbqs->hbqPutIdx) && + (j < (hbqs->entry_count+low))) { + len += snprintf(buf+len, size-len, "Unused\n"); + goto skipit; + } + } + + /* Get the Buffer info for the posted buffer */ + list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) { + hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); + phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff); + if (phys == hbqe->bde.addrLow) { + len += snprintf(buf+len, size-len, + "Buf%d: %p %06x\n", i, + hbq_buf->dbuf.virt, hbq_buf->tag); + found = 1; + break; + } + i++; + } + if (!found) { + len += snprintf(buf+len, size-len, "No DMAinfo?\n"); + } +skipit: + hbqe++; + if (len > LPFC_HBQINFO_SIZE - 54) + break; + } + spin_unlock_irq(&phba->hbalock); + return len; +} + +static int +lpfc_debugfs_dumpslim_data(struct lpfc_hba *phba, char *buf, int size) +{ + int len = 0; + int cnt, i, off; + uint32_t word0, word1, word2, word3; + uint32_t *ptr; + struct lpfc_pgp *pgpp; + struct lpfc_sli *psli = &phba->sli; + struct lpfc_sli_ring *pring; + + cnt = LPFC_DUMPSLIM_SIZE; + off = 0; + spin_lock_irq(&phba->hbalock); + + len += snprintf(buf+len, size-len, "SLIM Mailbox\n"); + ptr = (uint32_t *)phba->slim2p; + i = sizeof(MAILBOX_t); + while (i > 0) { + len += snprintf(buf+len, size-len, + "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), + *(ptr+5), *(ptr+6), *(ptr+7)); + ptr += 8; + i -= (8 * sizeof(uint32_t)); + off += (8 * sizeof(uint32_t)); + } + + len += snprintf(buf+len, size-len, "SLIM PCB\n"); + ptr = (uint32_t *)&phba->slim2p->pcb; + i = sizeof(PCB_t); + while (i > 0) { + len += snprintf(buf+len, size-len, + "%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + off, *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), + *(ptr+5), *(ptr+6), *(ptr+7)); + ptr += 8; + i -= (8 * sizeof(uint32_t)); + off += (8 * sizeof(uint32_t)); + } + + pgpp = (struct lpfc_pgp *)&phba->slim2p->mbx.us.s3_pgp.port; + pring = &psli->ring[0]; + len += snprintf(buf+len, size-len, + "Ring 0: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x) " + "RSP PutInx:%d Max:%d\n", + pgpp->cmdGetInx, pring->numCiocb, + pring->next_cmdidx, pring->local_getidx, pring->flag, + pgpp->rspPutInx, pring->numRiocb); + pgpp++; + + pring = &psli->ring[1]; + len += snprintf(buf+len, size-len, + "Ring 1: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x) " + "RSP PutInx:%d Max:%d\n", + pgpp->cmdGetInx, pring->numCiocb, + pring->next_cmdidx, pring->local_getidx, pring->flag, + pgpp->rspPutInx, pring->numRiocb); + pgpp++; + + pring = &psli->ring[2]; + len += snprintf(buf+len, size-len, + "Ring 2: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x) " + "RSP PutInx:%d Max:%d\n", + pgpp->cmdGetInx, pring->numCiocb, + pring->next_cmdidx, pring->local_getidx, pring->flag, + pgpp->rspPutInx, pring->numRiocb); + pgpp++; + + pring = &psli->ring[3]; + len += snprintf(buf+len, size-len, + "Ring 3: CMD GetInx:%d (Max:%d Next:%d Local:%d flg:x%x) " + "RSP PutInx:%d Max:%d\n", + pgpp->cmdGetInx, pring->numCiocb, + pring->next_cmdidx, pring->local_getidx, pring->flag, + pgpp->rspPutInx, pring->numRiocb); + + + ptr = (uint32_t *)&phba->slim2p->mbx.us.s3_pgp.hbq_get; + word0 = readl(phba->HAregaddr); + word1 = readl(phba->CAregaddr); + word2 = readl(phba->HSregaddr); + word3 = readl(phba->HCregaddr); + len += snprintf(buf+len, size-len, "HA:%08x CA:%08x HS:%08x HC:%08x\n", + word0, word1, word2, word3); + spin_unlock_irq(&phba->hbalock); + return len; +} + +static int lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) { int len = 0; @@ -204,7 +449,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) len += snprintf(buf+len, size-len, "RPI:%03d flag:x%08x ", ndlp->nlp_rpi, ndlp->nlp_flag); if (!ndlp->nlp_type) - len += snprintf(buf+len, size-len, "UNKNOWN_TYPE"); + len += snprintf(buf+len, size-len, "UNKNOWN_TYPE "); if (ndlp->nlp_type & NLP_FC_NODE) len += snprintf(buf+len, size-len, "FC_NODE "); if (ndlp->nlp_type & NLP_FABRIC) @@ -213,7 +458,9 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) len += snprintf(buf+len, size-len, "FCP_TGT sid:%d ", ndlp->nlp_sid); if (ndlp->nlp_type & NLP_FCP_INITIATOR) - len += snprintf(buf+len, size-len, "FCP_INITIATOR"); + len += snprintf(buf+len, size-len, "FCP_INITIATOR "); + len += snprintf(buf+len, size-len, "refcnt:%x", + atomic_read(&ndlp->kref.refcount)); len += snprintf(buf+len, size-len, "\n"); } spin_unlock_irq(shost->host_lock); @@ -227,7 +474,7 @@ lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt, uint32_t data1, uint32_t data2, uint32_t data3) { #ifdef CONFIG_LPFC_DEBUG_FS - struct lpfc_disc_trc *dtp; + struct lpfc_debugfs_trc *dtp; int index; if (!(lpfc_debugfs_mask_disc_trc & mask)) @@ -244,7 +491,32 @@ lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt, dtp->data1 = data1; dtp->data2 = data2; dtp->data3 = data3; - dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_disc_trc_cnt); + dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt); + dtp->jif = jiffies; +#endif + return; +} + +inline void +lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt, + uint32_t data1, uint32_t data2, uint32_t data3) +{ +#ifdef CONFIG_LPFC_DEBUG_FS + struct lpfc_debugfs_trc *dtp; + int index; + + if (!lpfc_debugfs_enable || !lpfc_debugfs_max_slow_ring_trc || + !phba || !phba->slow_ring_trc) + return; + + index = atomic_inc_return(&phba->slow_ring_trc_cnt) & + (lpfc_debugfs_max_slow_ring_trc - 1); + dtp = phba->slow_ring_trc + index; + dtp->fmt = fmt; + dtp->data1 = data1; + dtp->data2 = data2; + dtp->data3 = data3; + dtp->seq_cnt = atomic_inc_return(&lpfc_debugfs_seq_trc_cnt); dtp->jif = jiffies; #endif return; @@ -269,7 +541,7 @@ lpfc_debugfs_disc_trc_open(struct inode *inode, struct file *file) goto out; /* Round to page boundry */ - size = (lpfc_debugfs_max_disc_trc * LPFC_DISC_TRC_ENTRY_SIZE); + size = (lpfc_debugfs_max_disc_trc * LPFC_DEBUG_TRC_ENTRY_SIZE); size = PAGE_ALIGN(size); debug->buffer = kmalloc(size, GFP_KERNEL); @@ -287,6 +559,95 @@ out: } static int +lpfc_debugfs_slow_ring_trc_open(struct inode *inode, struct file *file) +{ + struct lpfc_hba *phba = inode->i_private; + struct lpfc_debug *debug; + int size; + int rc = -ENOMEM; + + if (!lpfc_debugfs_max_slow_ring_trc) { + rc = -ENOSPC; + goto out; + } + + debug = kmalloc(sizeof(*debug), GFP_KERNEL); + if (!debug) + goto out; + + /* Round to page boundry */ + size = (lpfc_debugfs_max_slow_ring_trc * LPFC_DEBUG_TRC_ENTRY_SIZE); + size = PAGE_ALIGN(size); + + debug->buffer = kmalloc(size, GFP_KERNEL); + if (!debug->buffer) { + kfree(debug); + goto out; + } + + debug->len = lpfc_debugfs_slow_ring_trc_data(phba, debug->buffer, size); + file->private_data = debug; + + rc = 0; +out: + return rc; +} + +static int +lpfc_debugfs_hbqinfo_open(struct inode *inode, struct file *file) +{ + struct lpfc_hba *phba = inode->i_private; + struct lpfc_debug *debug; + int rc = -ENOMEM; + + debug = kmalloc(sizeof(*debug), GFP_KERNEL); + if (!debug) + goto out; + + /* Round to page boundry */ + debug->buffer = kmalloc(LPFC_HBQINFO_SIZE, GFP_KERNEL); + if (!debug->buffer) { + kfree(debug); + goto out; + } + + debug->len = lpfc_debugfs_hbqinfo_data(phba, debug->buffer, + LPFC_HBQINFO_SIZE); + file->private_data = debug; + + rc = 0; +out: + return rc; +} + +static int +lpfc_debugfs_dumpslim_open(struct inode *inode, struct file *file) +{ + struct lpfc_hba *phba = inode->i_private; + struct lpfc_debug *debug; + int rc = -ENOMEM; + + debug = kmalloc(sizeof(*debug), GFP_KERNEL); + if (!debug) + goto out; + + /* Round to page boundry */ + debug->buffer = kmalloc(LPFC_DUMPSLIM_SIZE, GFP_KERNEL); + if (!debug->buffer) { + kfree(debug); + goto out; + } + + debug->len = lpfc_debugfs_dumpslim_data(phba, debug->buffer, + LPFC_DUMPSLIM_SIZE); + file->private_data = debug; + + rc = 0; +out: + return rc; +} + +static int lpfc_debugfs_nodelist_open(struct inode *inode, struct file *file) { struct lpfc_vport *vport = inode->i_private; @@ -372,6 +733,33 @@ static struct file_operations lpfc_debugfs_op_nodelist = { .release = lpfc_debugfs_release, }; +#undef lpfc_debugfs_op_hbqinfo +static struct file_operations lpfc_debugfs_op_hbqinfo = { + .owner = THIS_MODULE, + .open = lpfc_debugfs_hbqinfo_open, + .llseek = lpfc_debugfs_lseek, + .read = lpfc_debugfs_read, + .release = lpfc_debugfs_release, +}; + +#undef lpfc_debugfs_op_dumpslim +static struct file_operations lpfc_debugfs_op_dumpslim = { + .owner = THIS_MODULE, + .open = lpfc_debugfs_dumpslim_open, + .llseek = lpfc_debugfs_lseek, + .read = lpfc_debugfs_read, + .release = lpfc_debugfs_release, +}; + +#undef lpfc_debugfs_op_slow_ring_trc +static struct file_operations lpfc_debugfs_op_slow_ring_trc = { + .owner = THIS_MODULE, + .open = lpfc_debugfs_slow_ring_trc_open, + .llseek = lpfc_debugfs_lseek, + .read = lpfc_debugfs_read, + .release = lpfc_debugfs_release, +}; + static struct dentry *lpfc_debugfs_root = NULL; static atomic_t lpfc_debugfs_hba_count; #endif @@ -387,60 +775,146 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) if (!lpfc_debugfs_enable) return; - if (lpfc_debugfs_max_disc_trc) { - num = lpfc_debugfs_max_disc_trc - 1; - if (num & lpfc_debugfs_max_disc_trc) { - /* Change to be a power of 2 */ - num = lpfc_debugfs_max_disc_trc; - i = 0; - while (num > 1) { - num = num >> 1; - i++; - } - lpfc_debugfs_max_disc_trc = (1 << i); - printk(KERN_ERR - "lpfc_debugfs_max_disc_trc changed to %d\n", - lpfc_debugfs_max_disc_trc); - } - } - + /* Setup lpfc root directory */ if (!lpfc_debugfs_root) { lpfc_debugfs_root = debugfs_create_dir("lpfc", NULL); atomic_set(&lpfc_debugfs_hba_count, 0); - if (!lpfc_debugfs_root) + if (!lpfc_debugfs_root) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cannot create debugfs root\n"); goto debug_failed; + } } + if (!lpfc_debugfs_start_time) + lpfc_debugfs_start_time = jiffies; + /* Setup lpfcX directory for specific HBA */ snprintf(name, sizeof(name), "lpfc%d", phba->brd_no); if (!phba->hba_debugfs_root) { phba->hba_debugfs_root = debugfs_create_dir(name, lpfc_debugfs_root); - if (!phba->hba_debugfs_root) + if (!phba->hba_debugfs_root) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cannot create debugfs hba\n"); goto debug_failed; + } atomic_inc(&lpfc_debugfs_hba_count); atomic_set(&phba->debugfs_vport_count, 0); + + /* Setup hbqinfo */ + snprintf(name, sizeof(name), "hbqinfo"); + phba->debug_hbqinfo = + debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, + phba->hba_debugfs_root, + phba, &lpfc_debugfs_op_hbqinfo); + if (!phba->debug_hbqinfo) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cannot create debugfs hbqinfo\n"); + goto debug_failed; + } + + /* Setup dumpslim */ + snprintf(name, sizeof(name), "dumpslim"); + phba->debug_dumpslim = + debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, + phba->hba_debugfs_root, + phba, &lpfc_debugfs_op_dumpslim); + if (!phba->debug_dumpslim) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cannot create debugfs dumpslim\n"); + goto debug_failed; + } + + /* Setup slow ring trace */ + if (lpfc_debugfs_max_slow_ring_trc) { + num = lpfc_debugfs_max_slow_ring_trc - 1; + if (num & lpfc_debugfs_max_slow_ring_trc) { + /* Change to be a power of 2 */ + num = lpfc_debugfs_max_slow_ring_trc; + i = 0; + while (num > 1) { + num = num >> 1; + i++; + } + lpfc_debugfs_max_slow_ring_trc = (1 << i); + printk(KERN_ERR + "lpfc_debugfs_max_disc_trc changed to " + "%d\n", lpfc_debugfs_max_disc_trc); + } + } + + + snprintf(name, sizeof(name), "slow_ring_trace"); + phba->debug_slow_ring_trc = + debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, + phba->hba_debugfs_root, + phba, &lpfc_debugfs_op_slow_ring_trc); + if (!phba->debug_slow_ring_trc) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cannot create debugfs " + "slow_ring_trace\n"); + goto debug_failed; + } + if (!phba->slow_ring_trc) { + phba->slow_ring_trc = kmalloc( + (sizeof(struct lpfc_debugfs_trc) * + lpfc_debugfs_max_slow_ring_trc), + GFP_KERNEL); + if (!phba->slow_ring_trc) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cannot create debugfs " + "slow_ring buffer\n"); + goto debug_failed; + } + atomic_set(&phba->slow_ring_trc_cnt, 0); + memset(phba->slow_ring_trc, 0, + (sizeof(struct lpfc_debugfs_trc) * + lpfc_debugfs_max_slow_ring_trc)); + } } snprintf(name, sizeof(name), "vport%d", vport->vpi); if (!vport->vport_debugfs_root) { vport->vport_debugfs_root = debugfs_create_dir(name, phba->hba_debugfs_root); - if (!vport->vport_debugfs_root) + if (!vport->vport_debugfs_root) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cant create debugfs"); goto debug_failed; + } atomic_inc(&phba->debugfs_vport_count); } - if (!lpfc_debugfs_start_time) - lpfc_debugfs_start_time = jiffies; + if (lpfc_debugfs_max_disc_trc) { + num = lpfc_debugfs_max_disc_trc - 1; + if (num & lpfc_debugfs_max_disc_trc) { + /* Change to be a power of 2 */ + num = lpfc_debugfs_max_disc_trc; + i = 0; + while (num > 1) { + num = num >> 1; + i++; + } + lpfc_debugfs_max_disc_trc = (1 << i); + printk(KERN_ERR + "lpfc_debugfs_max_disc_trc changed to %d\n", + lpfc_debugfs_max_disc_trc); + } + } vport->disc_trc = kmalloc( - (sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc), + (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc), GFP_KERNEL); - if (!vport->disc_trc) + if (!vport->disc_trc) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cannot create debugfs disc trace " + "buffer\n"); goto debug_failed; + } + atomic_set(&vport->disc_trc_cnt, 0); memset(vport->disc_trc, 0, - (sizeof(struct lpfc_disc_trc) * lpfc_debugfs_max_disc_trc)); + (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc)); snprintf(name, sizeof(name), "discovery_trace"); vport->debug_disc_trc = @@ -448,9 +922,9 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) vport->vport_debugfs_root, vport, &lpfc_debugfs_op_disc_trc); if (!vport->debug_disc_trc) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0409 Cannot create debugfs", - phba->brd_no); + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cannot create debugfs " + "discovery_trace\n"); goto debug_failed; } snprintf(name, sizeof(name), "nodelist"); @@ -459,9 +933,8 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) vport->vport_debugfs_root, vport, &lpfc_debugfs_op_nodelist); if (!vport->debug_nodelist) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0409 Cannot create debugfs", - phba->brd_no); + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, + "0409 Cant create debugfs nodelist"); goto debug_failed; } debug_failed: @@ -488,21 +961,45 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) debugfs_remove(vport->debug_nodelist); /* nodelist */ vport->debug_nodelist = NULL; } + if (vport->vport_debugfs_root) { debugfs_remove(vport->vport_debugfs_root); /* vportX */ vport->vport_debugfs_root = NULL; atomic_dec(&phba->debugfs_vport_count); } if (atomic_read(&phba->debugfs_vport_count) == 0) { - debugfs_remove(vport->phba->hba_debugfs_root); /* lpfcX */ - vport->phba->hba_debugfs_root = NULL; - atomic_dec(&lpfc_debugfs_hba_count); + + if (phba->debug_hbqinfo) { + debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */ + phba->debug_hbqinfo = NULL; + } + if (phba->debug_dumpslim) { + debugfs_remove(phba->debug_dumpslim); /* dumpslim */ + phba->debug_dumpslim = NULL; + } + if (phba->slow_ring_trc) { + kfree(phba->slow_ring_trc); + phba->slow_ring_trc = NULL; + } + if (phba->debug_slow_ring_trc) { + /* slow_ring_trace */ + debugfs_remove(phba->debug_slow_ring_trc); + phba->debug_slow_ring_trc = NULL; + } + + if (phba->hba_debugfs_root) { + debugfs_remove(phba->hba_debugfs_root); /* lpfcX */ + phba->hba_debugfs_root = NULL; + atomic_dec(&lpfc_debugfs_hba_count); + } + if (atomic_read(&lpfc_debugfs_hba_count) == 0) { debugfs_remove(lpfc_debugfs_root); /* lpfc */ lpfc_debugfs_root = NULL; } } #endif + return; } diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h index fffb678426a..31e86a55391 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.h +++ b/drivers/scsi/lpfc/lpfc_debugfs.h @@ -22,7 +22,7 @@ #define _H_LPFC_DEBUG_FS #ifdef CONFIG_LPFC_DEBUG_FS -struct lpfc_disc_trc { +struct lpfc_debugfs_trc { char *fmt; uint32_t data1; uint32_t data2; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 33fbc166694..8085900635d 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -63,10 +63,10 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) return 0; /* Pending Link Event during Discovery */ - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0237 Pending Link Event during " - "Discovery: State x%x\n", - phba->brd_no, vport->vpi, phba->pport->port_state); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0237 Pending Link Event during " + "Discovery: State x%x\n", + phba->pport->port_state); /* CLEAR_LA should re-enable link attention events and * we should then imediately take a LATT event. The @@ -196,9 +196,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, bpl->tus.w = le32_to_cpu(bpl->tus.w); } - /* Save for completion so we can release these resources */ - if (elscmd != ELS_CMD_LS_RJT) - elsiocb->context1 = lpfc_nlp_get(ndlp); + elsiocb->context1 = lpfc_nlp_get(ndlp); elsiocb->context2 = pcmd; elsiocb->context3 = pbuflist; elsiocb->retry = retry; @@ -208,23 +206,21 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, if (prsp) { list_add(&prsp->list, &pcmd->list); } - if (expectRsp) { /* Xmit ELS command <elsCmd> to remote NPORT <did> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0116 Xmit ELS command x%x to remote " - "NPORT x%x I/O tag: x%x, port state: x%x\n", - phba->brd_no, vport->vpi, elscmd, did, - elsiocb->iotag, vport->port_state); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0116 Xmit ELS command x%x to remote " + "NPORT x%x I/O tag: x%x, port state: x%x\n", + elscmd, did, elsiocb->iotag, + vport->port_state); } else { /* Xmit ELS response <elsCmd> to remote NPORT <did> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0117 Xmit ELS response x%x to remote " - "NPORT x%x I/O tag: x%x, size: x%x\n", - phba->brd_no, vport->vpi, elscmd, - ndlp->nlp_DID, elsiocb->iotag, cmdSize); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0117 Xmit ELS response x%x to remote " + "NPORT x%x I/O tag: x%x, size: x%x\n", + elscmd, ndlp->nlp_DID, elsiocb->iotag, + cmdSize); } - return elsiocb; } @@ -285,9 +281,8 @@ fail_free_mbox: fail: lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0249 Cannot issue Register Fabric login\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0249 Cannot issue Register Fabric login\n"); return -ENXIO; } @@ -340,20 +335,19 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { if (sp->cmn.response_multiple_NPort) { - lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT, - "%d:1816 FLOGI NPIV supported, " - "response data 0x%x\n", - phba->brd_no, - sp->cmn.response_multiple_NPort); + lpfc_printf_vlog(vport, KERN_WARNING, + LOG_ELS | LOG_VPORT, + "1816 FLOGI NPIV supported, " + "response data 0x%x\n", + sp->cmn.response_multiple_NPort); phba->link_flag |= LS_NPIV_FAB_SUPPORTED; - } else { /* Because we asked f/w for NPIV it still expects us - to call reg_vnpid atleast for the physcial host */ - lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT, - "%d:1817 Fabric does not support NPIV " - "- configuring single port mode.\n", - phba->brd_no); + to call reg_vnpid atleast for the physcial host */ + lpfc_printf_vlog(vport, KERN_WARNING, + LOG_ELS | LOG_VPORT, + "1817 Fabric does not support NPIV " + "- configuring single port mode.\n"); phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; } } @@ -518,16 +512,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * alpa map would take too long otherwise. */ if (phba->alpa_map[0] == 0) { - phba->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; + vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; } /* FLOGI failure */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0100 FLOGI failure Data: x%x x%x " - "x%x\n", - phba->brd_no, vport->vpi, - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0100 FLOGI failure Data: x%x x%x " + "x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout); goto flogifail; } @@ -540,12 +533,11 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, sp = prsp->virt + sizeof(uint32_t); /* FLOGI completes successfully */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0101 FLOGI completes sucessfully " - "Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, - irsp->un.ulpWord[4], sp->cmn.e_d_tov, - sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0101 FLOGI completes sucessfully " + "Data: x%x x%x x%x x%x\n", + irsp->un.ulpWord[4], sp->cmn.e_d_tov, + sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution); if (vport->port_state == LPFC_FLOGI) { /* @@ -662,8 +654,8 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) /* Abort outstanding I/O on NPort <nlp_DID> */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d:0201 Abort outstanding I/O on NPort x%x\n", - phba->brd_no, Fabric_DID); + "0201 Abort outstanding I/O on NPort x%x\n", + Fabric_DID); pring = &phba->sli.ring[LPFC_ELS_RING]; @@ -736,18 +728,16 @@ static void lpfc_more_plogi(struct lpfc_vport *vport) { int sentplogi; - struct lpfc_hba *phba = vport->phba; if (vport->num_disc_nodes) vport->num_disc_nodes--; /* Continue discovery with <num_disc_nodes> PLOGIs to go */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0232 Continue discovery with %d PLOGIs to go " - "Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, vport->num_disc_nodes, - vport->fc_plogi_cnt, vport->fc_flag, vport->port_state); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0232 Continue discovery with %d PLOGIs to go " + "Data: x%x x%x x%x\n", + vport->num_disc_nodes, vport->fc_plogi_cnt, + vport->fc_flag, vport->port_state); /* Check to see if there are more PLOGIs to be sent */ if (vport->fc_flag & FC_NLP_MORE) /* go thru NPR nodes and issue any remaining ELS PLOGIs */ @@ -833,11 +823,12 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); if (!ndlp) { - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0136 PLOGI completes to NPort x%x " - "with no ndlp. Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, irsp->un.elsreq64.remoteID, - irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpIoTag); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0136 PLOGI completes to NPort x%x " + "with no ndlp. Data: x%x x%x x%x\n", + irsp->un.elsreq64.remoteID, + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpIoTag); goto out; } @@ -851,13 +842,11 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, rc = 0; /* PLOGI completes to NPort <nlp_DID> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0102 PLOGI completes to NPort x%x " - "Data: x%x x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, ndlp->nlp_DID, - irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout, disc, vport->num_disc_nodes); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0102 PLOGI completes to NPort x%x " + "Data: x%x x%x x%x x%x x%x\n", + ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout, disc, vport->num_disc_nodes); /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(vport)) { spin_lock_irq(shost->host_lock); @@ -881,17 +870,14 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } goto out; } - /* PLOGI failed */ if (ndlp->nlp_DID == NameServer_DID) { lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0250 Nameserver login error: " - "0x%x / 0x%x\n", - phba->brd_no, vport->vpi, - irsp->ulpStatus, irsp->un.ulpWord[4]); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0250 Nameserver login error: " + "0x%x / 0x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4]); } - /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ if (lpfc_error_lost_link(irsp)) { rc = NLP_STE_FREED_NODE; @@ -1017,14 +1003,12 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "PRLI cmpl: status:x%x/x%x did:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID); - /* PRLI completes to NPort <nlp_DID> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0103 PRLI completes to NPort x%x " - "Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, ndlp->nlp_DID, - irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout, - vport->num_disc_nodes); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0103 PRLI completes to NPort x%x " + "Data: x%x x%x x%x x%x\n", + ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout, vport->num_disc_nodes); vport->fc_prli_sent--; /* Check to see if link went down during discovery */ @@ -1129,18 +1113,15 @@ static void lpfc_more_adisc(struct lpfc_vport *vport) { int sentadisc; - struct lpfc_hba *phba = vport->phba; if (vport->num_disc_nodes) vport->num_disc_nodes--; - /* Continue discovery with <num_disc_nodes> ADISCs to go */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0210 Continue discovery with %d ADISCs to go " - "Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, vport->num_disc_nodes, - vport->fc_adisc_cnt, vport->fc_flag, vport->port_state); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0210 Continue discovery with %d ADISCs to go " + "Data: x%x x%x x%x\n", + vport->num_disc_nodes, vport->fc_adisc_cnt, + vport->fc_flag, vport->port_state); /* Check to see if there are more ADISCs to be sent */ if (vport->fc_flag & FC_NLP_MORE) { lpfc_set_disctmo(vport); @@ -1206,15 +1187,12 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC); spin_unlock_irq(shost->host_lock); - /* ADISC completes to NPort <nlp_DID> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0104 ADISC completes to NPort x%x " - "Data: x%x x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, ndlp->nlp_DID, - irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout, - disc, vport->num_disc_nodes); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0104 ADISC completes to NPort x%x " + "Data: x%x x%x x%x x%x x%x\n", + ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout, disc, vport->num_disc_nodes); /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(vport)) { spin_lock_irq(shost->host_lock); @@ -1374,15 +1352,12 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "LOGO cmpl: status:x%x/x%x did:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID); - /* LOGO completes to NPort <nlp_DID> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0105 LOGO completes to NPort x%x " - "Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, ndlp->nlp_DID, - irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout, - vport->num_disc_nodes); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0105 LOGO completes to NPort x%x " + "Data: x%x x%x x%x x%x\n", + ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout, vport->num_disc_nodes); /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(vport)) goto out; @@ -1488,15 +1463,11 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "ELS cmd cmpl: status:x%x/x%x did:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.elsreq64.remoteID); - /* ELS cmd tag <ulpIoTag> completes */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0106 ELS cmd tag x%x completes Data: x%x x%x " - "x%x\n", - phba->brd_no, vport->vpi, - irsp->ulpIoTag, irsp->ulpStatus, - irsp->un.ulpWord[4], irsp->ulpTimeout); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", + irsp->ulpIoTag, irsp->ulpStatus, + irsp->un.ulpWord[4], irsp->ulpTimeout); /* Check to see if link went down during discovery */ lpfc_els_chk_latt(vport); lpfc_els_free_iocb(phba, cmdiocb); @@ -1831,13 +1802,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, case IOERR_ILLEGAL_COMMAND: if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) && (cmd == ELS_CMD_FDISC)) { - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0124 FDISC failed (3/6) retrying...\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0124 FDISC failed (3/6) " + "retrying...\n"); lpfc_mbx_unreg_vpi(vport); retry = 1; - /* Always retry for this case */ - cmdiocb->retry = 0; + /* FDISC retry policy */ + maxretry = 48; + if (cmdiocb->retry >= 32) + delay = 1000; } break; @@ -1898,10 +1871,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && (cmd == ELS_CMD_FDISC) && (stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){ - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0125 FDISC Failed (x%x)." - " Fabric out of resources\n", - phba->brd_no, vport->vpi, stat.un.lsRjtError); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0125 FDISC Failed (x%x). " + "Fabric out of resources\n", + stat.un.lsRjtError); lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_RSCS); } @@ -1913,8 +1886,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, delay = 1000; maxretry = 48; } else if (cmd == ELS_CMD_FDISC) { - /* Always retry for this case */ - cmdiocb->retry = 0; + /* FDISC retry policy */ + maxretry = 48; + if (cmdiocb->retry >= 32) + delay = 1000; } retry = 1; break; @@ -1926,10 +1901,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) || (stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID)) ) { - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0123 FDISC Failed (x%x)." - " Fabric Detected Bad WWN\n", - phba->brd_no, vport->vpi, stat.un.lsRjtError); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0123 FDISC Failed (x%x). " + "Fabric Detected Bad WWN\n", + stat.un.lsRjtError); lpfc_vport_set_state(vport, FC_VPORT_FABRIC_REJ_WWN); } @@ -1959,11 +1934,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (retry) { /* Retry ELS command <elsCmd> to remote NPORT <did> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0107 Retry ELS command x%x to remote " - "NPORT x%x Data: x%x x%x\n", - phba->brd_no, vport->vpi, - cmd, did, cmdiocb->retry, delay); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0107 Retry ELS command x%x to remote " + "NPORT x%x Data: x%x x%x\n", + cmd, did, cmdiocb->retry, delay); if (((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) && ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) || @@ -2031,14 +2005,12 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, return 1; } } - /* No retry ELS command <elsCmd> to remote NPORT <did> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0108 No retry ELS command x%x to remote " - "NPORT x%x Data: x%x\n", - phba->brd_no, vport->vpi, - cmd, did, cmdiocb->retry); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0108 No retry ELS command x%x to remote " + "NPORT x%x Retried:%d Error:x%x/%x\n", + cmd, did, cmdiocb->retry, irsp->ulpStatus, + irsp->un.ulpWord[4]); return 0; } @@ -2087,14 +2059,12 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, "ACC LOGO cmpl: status:x%x/x%x did:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID); - /* ACC to LOGO completes to NPort <nlp_DID> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0109 ACC to LOGO completes to NPort x%x " - "Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0109 ACC to LOGO completes to NPort x%x " + "Data: x%x x%x x%x\n", + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); switch (ndlp->nlp_state) { case NLP_STE_UNUSED_NODE: /* node is just allocated */ lpfc_drop_node(vport, ndlp); @@ -2153,20 +2123,17 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, - "ACC cmpl: status:x%x/x%x did:x%x", + "ELS rsp cmpl: status:x%x/x%x did:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->un.rcvels.remoteID); - + cmdiocb->iocb.un.elsreq64.remoteID); /* ELS response tag <ulpIoTag> completes */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0110 ELS response tag x%x completes " - "Data: x%x x%x x%x x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, - cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, - rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout, - ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, - ndlp->nlp_rpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0110 ELS response tag x%x completes " + "Data: x%x x%x x%x x%x x%x x%x x%x\n", + cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, + rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); if (mbox) { if ((rspiocb->iocb.ulpStatus == 0) && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { @@ -2219,7 +2186,7 @@ out: int lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, - LPFC_MBOXQ_t *mbox, uint8_t newnode) + LPFC_MBOXQ_t *mbox) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; @@ -2305,20 +2272,13 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, default: return 1; } - - if (newnode) { - lpfc_nlp_put(ndlp); - elsiocb->context1 = NULL; - } - /* Xmit ELS ACC response tag <ulpIoTag> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0128 Xmit ELS ACC response tag x%x, XRI: x%x, " - "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n", - phba->brd_no, vport->vpi, elsiocb->iotag, - elsiocb->iocb.ulpContext, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0128 Xmit ELS ACC response tag x%x, XRI: x%x, " + "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n", + elsiocb->iotag, elsiocb->iocb.ulpContext, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); if (ndlp->nlp_flag & NLP_LOGO_ACC) { spin_lock_irq(shost->host_lock); ndlp->nlp_flag &= ~NLP_LOGO_ACC; @@ -2370,20 +2330,17 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, pcmd += sizeof(uint32_t); *((uint32_t *) (pcmd)) = rejectError; - if (mbox) { + if (mbox) elsiocb->context_un.mbox = mbox; - elsiocb->context1 = lpfc_nlp_get(ndlp); - } /* Xmit ELS RJT <err> response tag <ulpIoTag> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0129 Xmit ELS RJT x%x response tag x%x " - "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, " - "rpi x%x\n", - phba->brd_no, vport->vpi, rejectError, elsiocb->iotag, - elsiocb->iocb.ulpContext, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0129 Xmit ELS RJT x%x response tag x%x " + "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, " + "rpi x%x\n", + rejectError, elsiocb->iotag, + elsiocb->iocb.ulpContext, ndlp->nlp_DID, + ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, "Issue LS_RJT: did:x%x flg:x%x err:x%x", ndlp->nlp_DID, ndlp->nlp_flag, rejectError); @@ -2391,6 +2348,15 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, phba->fc_stat.elsXmitLSRJT++; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); + + /* If the node is in the UNUSED state, and we are sending + * a reject, we are done with it. Release driver reference + * count here. The outstanding els will release its reference on + * completion and the node can be freed then. + */ + if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) + lpfc_nlp_put(ndlp); + if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); return 1; @@ -2423,13 +2389,12 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, icmd->ulpContext = oldcmd->ulpContext; /* Xri */ /* Xmit ADISC ACC response tag <ulpIoTag> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0130 Xmit ADISC ACC response iotag x%x xri: " - "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n", - phba->brd_no, vport->vpi, elsiocb->iotag, - elsiocb->iocb.ulpContext, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0130 Xmit ADISC ACC response iotag x%x xri: " + "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n", + elsiocb->iotag, elsiocb->iocb.ulpContext, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = ELS_CMD_ACC; @@ -2483,15 +2448,13 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, icmd = &elsiocb->iocb; oldcmd = &oldiocb->iocb; icmd->ulpContext = oldcmd->ulpContext; /* Xri */ - /* Xmit PRLI ACC response tag <ulpIoTag> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0131 Xmit PRLI ACC response tag x%x xri x%x, " - "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", - phba->brd_no, vport->vpi, elsiocb->iotag, - elsiocb->iocb.ulpContext, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0131 Xmit PRLI ACC response tag x%x xri x%x, " + "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", + elsiocb->iotag, elsiocb->iocb.ulpContext, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)); @@ -2565,16 +2528,11 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, icmd = &elsiocb->iocb; oldcmd = &oldiocb->iocb; icmd->ulpContext = oldcmd->ulpContext; /* Xri */ - /* Xmit RNID ACC response tag <ulpIoTag> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0132 Xmit RNID ACC response tag x%x " - "xri x%x\n", - phba->brd_no, vport->vpi, elsiocb->iotag, - elsiocb->iocb.ulpContext); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0132 Xmit RNID ACC response tag x%x xri x%x\n", + elsiocb->iotag, elsiocb->iocb.ulpContext); pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); - *((uint32_t *) (pcmd)) = ELS_CMD_ACC; pcmd += sizeof(uint32_t); @@ -2641,7 +2599,7 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport) sentadisc++; vport->num_disc_nodes++; if (vport->num_disc_nodes >= - vport->phba->cfg_discovery_threads) { + vport->cfg_discovery_threads) { spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_NLP_MORE; spin_unlock_irq(shost->host_lock); @@ -2676,7 +2634,7 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport) sentplogi++; vport->num_disc_nodes++; if (vport->num_disc_nodes >= - vport->phba->cfg_discovery_threads) { + vport->cfg_discovery_threads) { spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_NLP_MORE; spin_unlock_irq(shost->host_lock); @@ -2717,7 +2675,6 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) D_ID rscn_did; uint32_t *lp; uint32_t payload_len, i; - struct lpfc_hba *phba = vport->phba; ns_did.un.word = did; @@ -2752,12 +2709,10 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) break; default: /* Unknown Identifier in RSCN node */ - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0217 Unknown " - "Identifier in RSCN payload " - "Data: x%x\n", - phba->brd_no, vport->vpi, - rscn_did.un.word); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0217 Unknown Identifier in " + "RSCN payload Data: x%x\n", + rscn_did.un.word); case 3: /* Whole Fabric effected */ return did; } @@ -2796,12 +2751,11 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) static int lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, - struct lpfc_nodelist *ndlp, uint8_t newnode) + struct lpfc_nodelist *ndlp) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; struct lpfc_dmabuf *pcmd; - struct lpfc_vport *next_vport; uint32_t *lp, *datap; IOCB_t *icmd; uint32_t payload_len, length, nportid, *cmd; @@ -2815,13 +2769,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK); payload_len -= sizeof(uint32_t); /* take off word 0 */ - /* RSCN received */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0214 RSCN received Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, vport->fc_flag, payload_len, - *lp, rscn_cnt); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0214 RSCN received Data: x%x x%x x%x x%x\n", + vport->fc_flag, payload_len, *lp, rscn_cnt); for (i = 0; i < payload_len/sizeof(uint32_t); i++) fc_host_post_event(shost, fc_get_event_number(), FCH_EVT_RSCN, lp[i]); @@ -2834,8 +2785,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x", ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); - lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, - newnode); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); return 0; } @@ -2843,7 +2793,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, * just ACC and ignore it. */ if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && - !(phba->cfg_peer_port_login)) { + !(vport->cfg_peer_port_login)) { i = payload_len; datap = lp; while (i > 0) { @@ -2851,28 +2801,23 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, nportid = ((be32_to_cpu(nportid)) & Mask_DID); i -= sizeof(uint32_t); rscn_id++; - list_for_each_entry(next_vport, &phba->port_list, - listentry) { - if (nportid == next_vport->fc_myDID) { - hba_id++; - break; - } - } + if (lpfc_find_vport_by_did(phba, nportid)) + hba_id++; } if (rscn_id == hba_id) { /* ALL NPortIDs in RSCN are on HBA */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, vport->fc_flag, payload_len, - *lp, rscn_cnt); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0214 Ignore RSCN " + "Data: x%x x%x x%x x%x\n", + vport->fc_flag, payload_len, + *lp, rscn_cnt); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, "RCV RSCN vport: did:x%x/ste:x%x flg:x%x", ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, - ndlp, NULL, newnode); + ndlp, NULL); return 0; } } @@ -2911,27 +2856,24 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /* Deferred RSCN */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0235 Deferred RSCN " - "Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, - vport->fc_rscn_id_cnt, vport->fc_flag, - vport->port_state); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0235 Deferred RSCN " + "Data: x%x x%x x%x\n", + vport->fc_rscn_id_cnt, vport->fc_flag, + vport->port_state); } else { spin_lock_irq(shost->host_lock); vport->fc_flag |= FC_RSCN_DISCOVERY; spin_unlock_irq(shost->host_lock); /* ReDiscovery RSCN */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0234 ReDiscovery RSCN " - "Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, - vport->fc_rscn_id_cnt, vport->fc_flag, - vport->port_state); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0234 ReDiscovery RSCN " + "Data: x%x x%x x%x\n", + vport->fc_rscn_id_cnt, vport->fc_flag, + vport->port_state); } /* Send back ACC */ - lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, - newnode); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); /* send RECOVERY event for ALL nodes that match RSCN payload */ lpfc_rscn_recovery_check(vport); @@ -2956,7 +2898,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lpfc_set_disctmo(vport); /* Send back ACC */ - lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); /* send RECOVERY event for ALL nodes that match RSCN payload */ lpfc_rscn_recovery_check(vport); @@ -2980,11 +2922,10 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) lpfc_set_disctmo(vport); /* RSCN processed */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0215 RSCN processed Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, - vport->fc_flag, 0, vport->fc_rscn_id_cnt, - vport->port_state); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0215 RSCN processed Data: x%x x%x x%x x%x\n", + vport->fc_flag, 0, vport->fc_rscn_id_cnt, + vport->port_state); /* To process RSCN, first compare RSCN data with NameServer */ vport->fc_ns_retry = 0; @@ -3026,7 +2967,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) static int lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, - struct lpfc_nodelist *ndlp, uint8_t newnode) + struct lpfc_nodelist *ndlp) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; @@ -3052,10 +2993,10 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, /* An FLOGI ELS command <elsCmd> was received from DID <did> in Loop Mode */ - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0113 An FLOGI ELS command x%x was " - "received from DID x%x in Loop Mode\n", - phba->brd_no, vport->vpi, cmd, did); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0113 An FLOGI ELS command x%x was " + "received from DID x%x in Loop Mode\n", + cmd, did); return 1; } @@ -3109,7 +3050,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /* Send back ACC */ - lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode); + lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); return 0; } @@ -3226,16 +3167,13 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt); rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord); rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt); - /* Xmit ELS RPS ACC response tag <ulpIoTag> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0118 Xmit ELS RPS ACC response tag x%x " - "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, " - "rpi x%x\n", - phba->brd_no, ndlp->vport->vpi, elsiocb->iotag, - elsiocb->iocb.ulpContext, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - + lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, + "0118 Xmit ELS RPS ACC response tag x%x xri x%x, " + "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", + elsiocb->iotag, elsiocb->iocb.ulpContext, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) @@ -3337,21 +3275,16 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, rpl_rsp.port_num_blk.portID = be32_to_cpu(vport->fc_myDID); memcpy(&rpl_rsp.port_num_blk.portName, &vport->fc_portname, sizeof(struct lpfc_name)); - memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t)); - - /* Xmit ELS RPL ACC response tag <ulpIoTag> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0120 Xmit ELS RPL ACC response tag x%x " - "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, " - "rpi x%x\n", - phba->brd_no, vport->vpi, elsiocb->iotag, - elsiocb->iocb.ulpContext, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0120 Xmit ELS RPL ACC response tag x%x " + "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, " + "rpi x%x\n", + elsiocb->iotag, elsiocb->iocb.ulpContext, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; - phba->fc_stat.elsXmitACC++; if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); @@ -3404,7 +3337,6 @@ static int lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, struct lpfc_nodelist *ndlp) { - struct lpfc_hba *phba = vport->phba; struct lpfc_dmabuf *pcmd; uint32_t *lp; IOCB_t *icmd; @@ -3418,12 +3350,9 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, cmd = *lp++; fp = (FARP *) lp; - /* FARP-REQ received from DID <did> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0601 FARP-REQ received from DID x%x\n", - phba->brd_no, vport->vpi, did); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0601 FARP-REQ received from DID x%x\n", did); /* We will only support match on WWPN or WWNN */ if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) { return 0; @@ -3471,7 +3400,6 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, uint32_t *lp; IOCB_t *icmd; uint32_t cmd, did; - struct lpfc_hba *phba = vport->phba; icmd = &cmdiocb->iocb; did = icmd->un.elsreq64.remoteID; @@ -3480,11 +3408,10 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, cmd = *lp++; /* FARP-RSP received from DID <did> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0600 FARP-RSP received from DID x%x\n", - phba->brd_no, vport->vpi, did); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0600 FARP-RSP received from DID x%x\n", did); /* ACCEPT the Farp resp request */ - lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); return 0; } @@ -3502,10 +3429,8 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, struct lpfc_hba *phba = vport->phba; /* FAN received */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0265 FAN received\n", - phba->brd_no, vport->vpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0265 FAN received\n"); icmd = &cmdiocb->iocb; did = icmd->un.elsreq64.remoteID; pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; @@ -3664,13 +3589,10 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) if (ndlp) remote_ID = ndlp->nlp_DID; } - - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0127 ELS timeout Data: x%x x%x x%x " - "x%x\n", - phba->brd_no, vport->vpi, els_command, - remote_ID, cmd->ulpCommand, cmd->ulpIoTag); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0127 ELS timeout Data: x%x x%x x%x " + "x%x\n", els_command, + remote_ID, cmd->ulpCommand, cmd->ulpIoTag); lpfc_sli_issue_abort_iotag(phba, pring, piocb); } spin_unlock_irq(&phba->hbalock); @@ -3741,6 +3663,50 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) return; } +void +lpfc_els_flush_all_cmd(struct lpfc_hba *phba) +{ + LIST_HEAD(completions); + struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; + struct lpfc_iocbq *tmp_iocb, *piocb; + IOCB_t *cmd = NULL; + + lpfc_fabric_abort_hba(phba); + spin_lock_irq(&phba->hbalock); + list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { + cmd = &piocb->iocb; + if (piocb->iocb_flag & LPFC_IO_LIBDFC) + continue; + /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */ + if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN || + cmd->ulpCommand == CMD_QUE_RING_BUF64_CN || + cmd->ulpCommand == CMD_CLOSE_XRI_CN || + cmd->ulpCommand == CMD_ABORT_XRI_CN) + continue; + list_move_tail(&piocb->list, &completions); + pring->txq_cnt--; + } + list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { + if (piocb->iocb_flag & LPFC_IO_LIBDFC) + continue; + lpfc_sli_issue_abort_iotag(phba, pring, piocb); + } + spin_unlock_irq(&phba->hbalock); + while (!list_empty(&completions)) { + piocb = list_get_first(&completions, struct lpfc_iocbq, list); + cmd = &piocb->iocb; + list_del_init(&piocb->list); + if (!piocb->iocb_cmpl) + lpfc_sli_release_iocbq(phba, piocb); + else { + cmd->ulpStatus = IOSTAT_LOCAL_REJECT; + cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; + (piocb->iocb_cmpl) (phba, piocb, piocb); + } + } + return; +} + static void lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb) @@ -3801,11 +3767,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, cmd &= ELS_CMD_MASK; } /* ELS command <elsCmd> received from NPORT <did> */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0112 ELS command x%x received from NPORT x%x " - "Data: x%x\n", phba->brd_no, vport->vpi, cmd, did, - vport->port_state); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0112 ELS command x%x received from NPORT x%x " + "Data: x%x\n", cmd, did, vport->port_state); switch (cmd) { case ELS_CMD_PLOGI: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -3829,7 +3793,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, did, vport->port_state, ndlp->nlp_flag); phba->fc_stat.elsRcvFLOGI++; - lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode); + lpfc_els_rcv_flogi(vport, elsiocb, ndlp); if (newnode) lpfc_drop_node(vport, ndlp); break; @@ -3859,7 +3823,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, break; case ELS_CMD_RSCN: phba->fc_stat.elsRcvRSCN++; - lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode); + lpfc_els_rcv_rscn(vport, elsiocb, ndlp); if (newnode) lpfc_drop_node(vport, ndlp); break; @@ -3974,10 +3938,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, rjt_err = LSRJT_INVALID_CMD; /* Unknown ELS command <elsCmd> received from NPORT <did> */ - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0115 Unknown ELS command x%x " - "received from NPORT x%x\n", - phba->brd_no, vport->vpi, cmd, did); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0115 Unknown ELS command x%x " + "received from NPORT x%x\n", cmd, did); if (newnode) lpfc_drop_node(vport, ndlp); break; @@ -3990,19 +3953,16 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp, NULL); - if (newnode) - lpfc_drop_node(vport, ndlp); } return; dropit: lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0111 Dropping received ELS cmd " + "(%d):0111 Dropping received ELS cmd " "Data: x%x x%x x%x\n", - phba->brd_no, vport ? vport->vpi : 0xffff, - icmd->ulpStatus, icmd->un.ulpWord[4], - icmd->ulpTimeout); + vport ? vport->vpi : 0xffff, icmd->ulpStatus, + icmd->un.ulpWord[4], icmd->ulpTimeout); phba->fc_stat.elsRcvDrop++; } @@ -4010,11 +3970,16 @@ static struct lpfc_vport * lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) { struct lpfc_vport *vport; + unsigned long flags; + spin_lock_irqsave(&phba->hbalock, flags); list_for_each_entry(vport, &phba->port_list, listentry) { - if (vport->vpi == vpi) + if (vport->vpi == vpi) { + spin_unlock_irqrestore(&phba->hbalock, flags); return vport; + } } + spin_unlock_irqrestore(&phba->hbalock, flags); return NULL; } @@ -4109,9 +4074,8 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) return; } lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0251 NameServer login: no memory\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0251 NameServer login: no memory\n"); return; } lpfc_nlp_init(vport, ndlp, NameServer_DID); @@ -4122,13 +4086,12 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) { lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0252 Cannot issue NameServer login\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0252 Cannot issue NameServer login\n"); return; } - if (phba->cfg_fdmi_on) { + if (vport->cfg_fdmi_on) { ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); if (ndlp_fdmi) { @@ -4155,9 +4118,9 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_nlp_put(ndlp); if (mb->mbxStatus) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d (%d):0915 Register VPI failed: 0x%x\n", - phba->brd_no, vport->vpi, mb->mbxStatus); + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + "0915 Register VPI failed: 0x%x\n", + mb->mbxStatus); switch (mb->mbxStatus) { case 0x11: /* unsupported feature */ @@ -4206,17 +4169,14 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; lpfc_vport_set_state(vport, FC_VPORT_FAILED); - - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d (%d):0253 Register VPI: Cannot send mbox\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + "0253 Register VPI: Can't send mbox\n"); } } else { lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d (%d):0254 Register VPI: no memory\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + "0254 Register VPI: no memory\n"); vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI; lpfc_nlp_put(ndlp); @@ -4235,11 +4195,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, IOCB_t *irsp = &rspiocb->iocb; struct lpfc_iocbq *piocb; - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0123 FDISC completes. x%x/x%x prevDID: x%x\n", - phba->brd_no, vport->vpi, - irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0123 FDISC completes. x%x/x%x prevDID: x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], + vport->fc_prevDID); /* Since all FDISCs are being single threaded, we * must reset the discovery timer for ALL vports * waiting to send FDISC when one completes. @@ -4256,13 +4215,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Check for retry */ if (lpfc_els_retry(phba, cmdiocb, rspiocb)) goto out; - /* FDISC failed */ - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0124 FDISC failed. (%d/%d)\n", - phba->brd_no, vport->vpi, - irsp->ulpStatus, irsp->un.ulpWord[4]); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0124 FDISC failed. (%d/%d)\n", + irsp->ulpStatus, irsp->un.ulpWord[4]); if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING) lpfc_vport_set_state(vport, FC_VPORT_FAILED); @@ -4328,10 +4284,8 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ELS_CMD_FDISC); if (!elsiocb) { lpfc_vport_set_state(vport, FC_VPORT_FAILED); - - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0255 Issue FDISC: no IOCB\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0255 Issue FDISC: no IOCB\n"); return 1; } @@ -4377,11 +4331,8 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (rc == IOCB_ERROR) { lpfc_els_free_iocb(phba, elsiocb); lpfc_vport_set_state(vport, FC_VPORT_FAILED); - - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0256 Issue FDISC: Cannot send IOCB\n", - phba->brd_no, vport->vpi); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0256 Issue FDISC: Cannot send IOCB\n"); return 1; } lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f2f4639eab5..c81c2b3228d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -83,10 +83,17 @@ lpfc_terminate_rport_io(struct fc_rport *rport) ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); if (ndlp->nlp_sid != NLP_NO_SID) { - lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], - ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); + lpfc_sli_abort_iocb(ndlp->vport, + &phba->sli.ring[phba->sli.fcp_ring], + ndlp->nlp_sid, 0, LPFC_CTX_TGT); } + /* + * A device is normally blocked for rediscovery and unblocked when + * devloss timeout happens. In case a vport is removed or driver + * unloaded before devloss timeout happens, we need to unblock here. + */ + scsi_target_unblock(&rport->dev); return; } @@ -194,32 +201,30 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) if (ndlp->nlp_sid != NLP_NO_SID) { warn_on = 1; /* flush the target */ - lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], - ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); + lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], + ndlp->nlp_sid, 0, LPFC_CTX_TGT); } if (vport->load_flag & FC_UNLOADING) warn_on = 0; if (warn_on) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0203 Devloss timeout on " - "WWPN %x:%x:%x:%x:%x:%x:%x:%x " - "NPort x%x Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, - *name, *(name+1), *(name+2), *(name+3), - *(name+4), *(name+5), *(name+6), *(name+7), - ndlp->nlp_DID, ndlp->nlp_flag, - ndlp->nlp_state, ndlp->nlp_rpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0203 Devloss timeout on " + "WWPN %x:%x:%x:%x:%x:%x:%x:%x " + "NPort x%x Data: x%x x%x x%x\n", + *name, *(name+1), *(name+2), *(name+3), + *(name+4), *(name+5), *(name+6), *(name+7), + ndlp->nlp_DID, ndlp->nlp_flag, + ndlp->nlp_state, ndlp->nlp_rpi); } else { - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0204 Devloss timeout on " - "WWPN %x:%x:%x:%x:%x:%x:%x:%x " - "NPort x%x Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, - *name, *(name+1), *(name+2), *(name+3), - *(name+4), *(name+5), *(name+6), *(name+7), - ndlp->nlp_DID, ndlp->nlp_flag, - ndlp->nlp_state, ndlp->nlp_rpi); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0204 Devloss timeout on " + "WWPN %x:%x:%x:%x:%x:%x:%x:%x " + "NPort x%x Data: x%x x%x x%x\n", + *name, *(name+1), *(name+2), *(name+3), + *(name+4), *(name+5), *(name+6), *(name+7), + ndlp->nlp_DID, ndlp->nlp_flag, + ndlp->nlp_state, ndlp->nlp_rpi); } if (!(vport->load_flag & FC_UNLOADING) && @@ -344,12 +349,14 @@ lpfc_work_list_done(struct lpfc_hba *phba) } -void +static void lpfc_work_done(struct lpfc_hba *phba) { struct lpfc_sli_ring *pring; uint32_t ha_copy, status, control, work_port_events; + struct lpfc_vport **vports; struct lpfc_vport *vport; + int i; spin_lock_irq(&phba->hbalock); ha_copy = phba->work_ha; @@ -364,48 +371,41 @@ lpfc_work_done(struct lpfc_hba *phba) if (ha_copy & HA_LATT) lpfc_handle_latt(phba); - - spin_lock_irq(&phba->hbalock); - list_for_each_entry(vport, &phba->port_list, listentry) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - - if (!scsi_host_get(shost)) { - continue; + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS; i++) { + /* + * We could have no vports in array if unloading, so if + * this happens then just use the pport + */ + if (vports[i] == NULL && i == 0) + vport = phba->pport; + else + vport = vports[i]; + if (vport == NULL) + break; + work_port_events = vport->work_port_events; + if (work_port_events & WORKER_DISC_TMO) + lpfc_disc_timeout_handler(vport); + if (work_port_events & WORKER_ELS_TMO) + lpfc_els_timeout_handler(vport); + if (work_port_events & WORKER_HB_TMO) + lpfc_hb_timeout_handler(phba); + if (work_port_events & WORKER_MBOX_TMO) + lpfc_mbox_timeout_handler(phba); + if (work_port_events & WORKER_FABRIC_BLOCK_TMO) + lpfc_unblock_fabric_iocbs(phba); + if (work_port_events & WORKER_FDMI_TMO) + lpfc_fdmi_timeout_handler(vport); + if (work_port_events & WORKER_RAMP_DOWN_QUEUE) + lpfc_ramp_down_queue_handler(phba); + if (work_port_events & WORKER_RAMP_UP_QUEUE) + lpfc_ramp_up_queue_handler(phba); + spin_lock_irq(&vport->work_port_lock); + vport->work_port_events &= ~work_port_events; + spin_unlock_irq(&vport->work_port_lock); } - spin_unlock_irq(&phba->hbalock); - work_port_events = vport->work_port_events; - - if (work_port_events & WORKER_DISC_TMO) - lpfc_disc_timeout_handler(vport); - - if (work_port_events & WORKER_ELS_TMO) - lpfc_els_timeout_handler(vport); - - if (work_port_events & WORKER_HB_TMO) - lpfc_hb_timeout_handler(phba); - - if (work_port_events & WORKER_MBOX_TMO) - lpfc_mbox_timeout_handler(phba); - - if (work_port_events & WORKER_FABRIC_BLOCK_TMO) - lpfc_unblock_fabric_iocbs(phba); - - if (work_port_events & WORKER_FDMI_TMO) - lpfc_fdmi_timeout_handler(vport); - - if (work_port_events & WORKER_RAMP_DOWN_QUEUE) - lpfc_ramp_down_queue_handler(phba); - - if (work_port_events & WORKER_RAMP_UP_QUEUE) - lpfc_ramp_up_queue_handler(phba); - - spin_lock_irq(&vport->work_port_lock); - vport->work_port_events &= ~work_port_events; - spin_unlock_irq(&vport->work_port_lock); - scsi_host_put(shost); - spin_lock_irq(&phba->hbalock); - } - spin_unlock_irq(&phba->hbalock); + lpfc_destroy_vport_work_array(vports); pring = &phba->sli.ring[LPFC_ELS_RING]; status = (ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING))); @@ -426,10 +426,19 @@ lpfc_work_done(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); control = readl(phba->HCregaddr); if (!(control & (HC_R0INT_ENA << LPFC_ELS_RING))) { + lpfc_debugfs_slow_ring_trc(phba, + "WRK Enable ring: cntl:x%x hacopy:x%x", + control, ha_copy, 0); + control |= (HC_R0INT_ENA << LPFC_ELS_RING); writel(control, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ } + else { + lpfc_debugfs_slow_ring_trc(phba, + "WRK Ring ok: cntl:x%x hacopy:x%x", + control, ha_copy, 0); + } spin_unlock_irq(&phba->hbalock); } lpfc_work_list_done(phba); @@ -439,32 +448,22 @@ static int check_work_wait_done(struct lpfc_hba *phba) { struct lpfc_vport *vport; - struct lpfc_sli_ring *pring; + struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; int rc = 0; spin_lock_irq(&phba->hbalock); list_for_each_entry(vport, &phba->port_list, listentry) { if (vport->work_port_events) { rc = 1; - goto exit; + break; } } - - if (phba->work_ha || (!list_empty(&phba->work_list)) || - kthread_should_stop()) { - rc = 1; - goto exit; - } - - pring = &phba->sli.ring[LPFC_ELS_RING]; - if (pring->flag & LPFC_DEFERRED_RING_EVENT) + if (rc || phba->work_ha || (!list_empty(&phba->work_list)) || + kthread_should_stop() || pring->flag & LPFC_DEFERRED_RING_EVENT) { rc = 1; -exit: - if (rc) phba->work_found++; - else + } else phba->work_found = 0; - spin_unlock_irq(&phba->hbalock); return rc; } @@ -592,7 +591,6 @@ lpfc_linkdown_port(struct lpfc_vport *vport) /* free any ndlp's on unused list */ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) - /* free any ndlp's in unused state */ if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) lpfc_drop_node(vport, ndlp); @@ -605,8 +603,9 @@ lpfc_linkdown(struct lpfc_hba *phba) { struct lpfc_vport *vport = phba->pport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - struct lpfc_vport *port_iterator; + struct lpfc_vport **vports; LPFC_MBOXQ_t *mb; + int i; if (phba->link_state == LPFC_LINK_DOWN) { return 0; @@ -617,13 +616,13 @@ lpfc_linkdown(struct lpfc_hba *phba) phba->pport->fc_flag &= ~FC_LBIT; } spin_unlock_irq(&phba->hbalock); - - list_for_each_entry(port_iterator, &phba->port_list, listentry) { - - /* Issue a LINK DOWN event to all nodes */ - lpfc_linkdown_port(port_iterator); - } - + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { + /* Issue a LINK DOWN event to all nodes */ + lpfc_linkdown_port(vports[i]); + } + lpfc_destroy_vport_work_array(vports); /* Clean up any firmware default rpi's */ mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (mb) { @@ -724,7 +723,8 @@ lpfc_linkup_port(struct lpfc_vport *vport) static int lpfc_linkup(struct lpfc_hba *phba) { - struct lpfc_vport *vport; + struct lpfc_vport **vports; + int i; phba->link_state = LPFC_LINK_UP; @@ -732,9 +732,11 @@ lpfc_linkup(struct lpfc_hba *phba) clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags); del_timer_sync(&phba->fabric_block_timer); - list_for_each_entry(vport, &phba->port_list, listentry) { - lpfc_linkup_port(vport); - } + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) + lpfc_linkup_port(vports[i]); + lpfc_destroy_vport_work_array(vports); if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) lpfc_issue_clear_la(phba, phba->pport); @@ -764,12 +766,10 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Check for error */ if ((mb->mbxStatus) && (mb->mbxStatus != 0x1601)) { /* CLEAR_LA mbox error <mbxStatus> state <hba_state> */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d (%d):0320 CLEAR_LA mbxStatus error x%x hba " - "state x%x\n", - phba->brd_no, vport->vpi, mb->mbxStatus, - vport->port_state); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + "0320 CLEAR_LA mbxStatus error x%x hba " + "state x%x\n", + mb->mbxStatus, vport->port_state); phba->link_state = LPFC_HBA_ERROR; goto out; } @@ -801,10 +801,8 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) out: /* Device Discovery completes */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0225 Device Discovery completes\n", - phba->brd_no, vport->vpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0225 Device Discovery completes\n"); mempool_free(pmb, phba->mbox_mem_pool); spin_lock_irq(shost->host_lock); @@ -861,19 +859,17 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) return; out: - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d (%d):0306 CONFIG_LINK mbxStatus error x%x " - "HBA state x%x\n", - phba->brd_no, vport->vpi, pmb->mb.mbxStatus, - vport->port_state); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + "0306 CONFIG_LINK mbxStatus error x%x " + "HBA state x%x\n", + pmb->mb.mbxStatus, vport->port_state); mempool_free(pmb, phba->mbox_mem_pool); lpfc_linkdown(phba); - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0200 CONFIG_LINK bad hba state x%x\n", - phba->brd_no, vport->vpi, vport->port_state); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0200 CONFIG_LINK bad hba state x%x\n", + vport->port_state); lpfc_issue_clear_la(phba, vport); return; @@ -890,12 +886,10 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Check for error */ if (mb->mbxStatus) { /* READ_SPARAM mbox error <mbxStatus> state <hba_state> */ - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d (%d):0319 READ_SPARAM mbxStatus error x%x " - "hba state x%x>\n", - phba->brd_no, vport->vpi, mb->mbxStatus, - vport->port_state); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + "0319 READ_SPARAM mbxStatus error x%x " + "hba state x%x>\n", + mb->mbxStatus, vport->port_state); lpfc_linkdown(phba); goto out; } @@ -978,7 +972,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) if (i == 0) { phba->alpa_map[0] = 0; } else { - if (phba->cfg_log_verbose & LOG_LINK_EVENT) { + if (vport->cfg_log_verbose & LOG_LINK_EVENT) { int numalpa, j, k; union { uint8_t pamap[16]; @@ -1004,10 +998,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT, - "%d:1304 Link Up Event " + "1304 Link Up Event " "ALPA map Data: x%x " "x%x x%x x%x\n", - phba->brd_no, un.pa.wd1, un.pa.wd2, un.pa.wd3, un.pa.wd4); } @@ -1015,7 +1008,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) } } else { if (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { - if (phba->max_vpi && phba->cfg_npiv_enable && + if (phba->max_vpi && phba->cfg_enable_npiv && (phba->sli_rev == 3)) phba->sli3_options |= LPFC_SLI3_NPIV_ENABLED; } @@ -1055,11 +1048,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) } out: lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d (%d):0263 Discovery Mailbox error: state: 0x%x : %p %p\n", - phba->brd_no, vport->vpi, - vport->port_state, sparam_mbox, cfglink_mbox); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + "0263 Discovery Mailbox error: state: 0x%x : %p %p\n", + vport->port_state, sparam_mbox, cfglink_mbox); lpfc_issue_clear_la(phba, vport); return; } @@ -1100,8 +1091,8 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) /* Check for error */ if (mb->mbxStatus) { lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, - "%d:1307 READ_LA mbox error x%x state x%x\n", - phba->brd_no, mb->mbxStatus, vport->port_state); + "1307 READ_LA mbox error x%x state x%x\n", + mb->mbxStatus, vport->port_state); lpfc_mbx_issue_link_down(phba); phba->link_state = LPFC_HBA_ERROR; goto lpfc_mbx_cmpl_read_la_free_mbuf; @@ -1132,26 +1123,26 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) phba->fc_stat.LinkUp++; if (phba->link_flag & LS_LOOPBACK_MODE) { lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, - "%d:1306 Link Up Event in loop back mode " - "x%x received Data: x%x x%x x%x x%x\n", - phba->brd_no, la->eventTag, phba->fc_eventTag, - la->granted_AL_PA, la->UlnkSpeed, - phba->alpa_map[0]); + "1306 Link Up Event in loop back mode " + "x%x received Data: x%x x%x x%x x%x\n", + la->eventTag, phba->fc_eventTag, + la->granted_AL_PA, la->UlnkSpeed, + phba->alpa_map[0]); } else { lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, - "%d:1303 Link Up Event x%x received " - "Data: x%x x%x x%x x%x\n", - phba->brd_no, la->eventTag, phba->fc_eventTag, - la->granted_AL_PA, la->UlnkSpeed, - phba->alpa_map[0]); + "1303 Link Up Event x%x received " + "Data: x%x x%x x%x x%x\n", + la->eventTag, phba->fc_eventTag, + la->granted_AL_PA, la->UlnkSpeed, + phba->alpa_map[0]); } lpfc_mbx_process_link_up(phba, la); } else { phba->fc_stat.LinkDown++; lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, - "%d:1305 Link Down Event x%x received " + "1305 Link Down Event x%x received " "Data: x%x x%x x%x\n", - phba->brd_no, la->eventTag, phba->fc_eventTag, + la->eventTag, phba->fc_eventTag, phba->pport->port_state, vport->fc_flag); lpfc_mbx_issue_link_down(phba); } @@ -1199,10 +1190,9 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) case 0x0011: case 0x0020: case 0x9700: - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d (%d):0911 cmpl_unreg_vpi, " - "mb status = 0x%x\n", - phba->brd_no, vport->vpi, mb->mbxStatus); + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, + "0911 cmpl_unreg_vpi, mb status = 0x%x\n", + mb->mbxStatus); break; } vport->unreg_vpi_cmpl = VPORT_OK; @@ -1231,9 +1221,8 @@ lpfc_mbx_unreg_vpi(struct lpfc_vport *vport) mbox->mbox_cmpl = lpfc_mbx_cmpl_unreg_vpi; rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT, - "%d (%d):1800 Could not issue unreg_vpi\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT, + "1800 Could not issue unreg_vpi\n"); mempool_free(mbox, phba->mbox_mem_pool); vport->unreg_vpi_cmpl = VPORT_ERROR; } @@ -1250,9 +1239,9 @@ lpfc_mbx_cmpl_reg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) case 0x0011: case 0x9601: case 0x9602: - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d (%d):0912 cmpl_reg_vpi, mb status = 0x%x\n", - phba->brd_no, vport->vpi, mb->mbxStatus); + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, + "0912 cmpl_reg_vpi, mb status = 0x%x\n", + mb->mbxStatus); lpfc_vport_set_state(vport, FC_VPORT_FAILED); spin_lock_irq(shost->host_lock); vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); @@ -1289,15 +1278,15 @@ void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { struct lpfc_vport *vport = pmb->vport; - struct lpfc_vport *next_vport; MAILBOX_t *mb = &pmb->mb; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); struct lpfc_nodelist *ndlp; - ndlp = (struct lpfc_nodelist *) pmb->context2; + struct lpfc_vport **vports; + int i; + ndlp = (struct lpfc_nodelist *) pmb->context2; pmb->context1 = NULL; pmb->context2 = NULL; - if (mb->mbxStatus) { lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); @@ -1314,10 +1303,9 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d (%d):0258 Register Fabric login error: 0x%x\n", - phba->brd_no, vport->vpi, mb->mbxStatus); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, + "0258 Register Fabric login error: 0x%x\n", + mb->mbxStatus); return; } @@ -1328,21 +1316,26 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_nlp_put(ndlp); /* Drop the reference from the mbox */ if (vport->port_state == LPFC_FABRIC_CFG_LINK) { - list_for_each_entry(next_vport, &phba->port_list, listentry) { - if (next_vport->port_type == LPFC_PHYSICAL_PORT) - continue; - - if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) - lpfc_initial_fdisc(next_vport); - else if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { - lpfc_vport_set_state(vport, - FC_VPORT_NO_FABRIC_SUPP); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0259 No NPIV Fabric " - "support\n", - phba->brd_no, vport->vpi); + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; + i < LPFC_MAX_VPORTS && vports[i] != NULL; + i++) { + if (vports[i]->port_type == LPFC_PHYSICAL_PORT) + continue; + if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) + lpfc_initial_fdisc(vports[i]); + else if (phba->sli3_options & + LPFC_SLI3_NPIV_ENABLED) { + lpfc_vport_set_state(vports[i], + FC_VPORT_NO_FABRIC_SUPP); + lpfc_printf_vlog(vport, KERN_ERR, + LOG_ELS, + "0259 No NPIV " + "Fabric support\n"); + } } - } + lpfc_destroy_vport_work_array(vports); lpfc_do_scr_ns_plogi(phba, vport); } @@ -1386,9 +1379,9 @@ out: return; } lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0260 Register NameServer error: 0x%x\n", - phba->brd_no, vport->vpi, mb->mbxStatus); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0260 Register NameServer error: 0x%x\n", + mb->mbxStatus); return; } @@ -1598,7 +1591,7 @@ lpfc_nlp_state_name(char *buffer, size_t size, int state) [NLP_STE_NPR_NODE] = "NPR", }; - if (state < ARRAY_SIZE(states) && states[state]) + if (state < NLP_STE_MAX_STATE && states[state]) strlcpy(buffer, states[state], size); else snprintf(buffer, size, "unknown (%d)", state); @@ -1613,12 +1606,11 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int old_state = ndlp->nlp_state; char name1[16], name2[16]; - lpfc_printf_log(vport->phba, KERN_INFO, LOG_NODE, - "%d (%d):0904 NPort state transition x%06x, %s -> %s\n", - vport->phba->brd_no, vport->vpi, - ndlp->nlp_DID, - lpfc_nlp_state_name(name1, sizeof(name1), old_state), - lpfc_nlp_state_name(name2, sizeof(name2), state)); + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, + "0904 NPort state transition x%06x, %s -> %s\n", + ndlp->nlp_DID, + lpfc_nlp_state_name(name1, sizeof(name1), old_state), + lpfc_nlp_state_name(name2, sizeof(name2), state)); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, "node statechg did:x%x old:%d ste:%d", @@ -1664,16 +1656,7 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) void lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - - if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) - lpfc_cancel_retry_delay_tmo(vport, ndlp); - if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) - lpfc_nlp_counters(vport, ndlp->nlp_state, -1); - spin_lock_irq(shost->host_lock); - list_del_init(&ndlp->nlp_listp); - ndlp->nlp_flag &= ~NLP_TARGET_REMOVE; - spin_unlock_irq(shost->host_lock); + lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); lpfc_nlp_put(ndlp); } @@ -1710,12 +1693,12 @@ lpfc_set_disctmo(struct lpfc_vport *vport) spin_unlock_irq(shost->host_lock); /* Start Discovery Timer state <hba_state> */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0247 Start Discovery Timer state x%x " - "Data: x%x x%lx x%x x%x\n", - phba->brd_no, vport->vpi, vport->port_state, tmo, - (unsigned long)&vport->fc_disctmo, vport->fc_plogi_cnt, - vport->fc_adisc_cnt); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0247 Start Discovery Timer state x%x " + "Data: x%x x%lx x%x x%x\n", + vport->port_state, tmo, + (unsigned long)&vport->fc_disctmo, vport->fc_plogi_cnt, + vport->fc_adisc_cnt); return; } @@ -1727,7 +1710,6 @@ int lpfc_can_disctmo(struct lpfc_vport *vport) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - struct lpfc_hba *phba = vport->phba; unsigned long iflags; lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, @@ -1746,13 +1728,11 @@ lpfc_can_disctmo(struct lpfc_vport *vport) } /* Cancel Discovery Timer state <hba_state> */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0248 Cancel Discovery Timer state x%x " - "Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, vport->port_state, - vport->fc_flag, vport->fc_plogi_cnt, - vport->fc_adisc_cnt); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0248 Cancel Discovery Timer state x%x " + "Data: x%x x%x x%x\n", + vport->port_state, vport->fc_flag, + vport->fc_plogi_cnt, vport->fc_adisc_cnt); return 0; } @@ -1935,10 +1915,9 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) rc = lpfc_sli_issue_mbox(phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); if (rc == MBX_NOT_FINISHED) { - lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT, - "%d (%d):1815 Could not issue " - "unreg_did (default rpis)\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT, + "1815 Could not issue " + "unreg_did (default rpis)\n"); mempool_free(mbox, phba->mbox_mem_pool); } } @@ -1957,12 +1936,11 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) struct lpfc_dmabuf *mp; /* Cleanup node for NPort <nlp_DID> */ - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d (%d):0900 Cleanup node for NPort x%x " - "Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, ndlp->nlp_DID, ndlp->nlp_flag, - ndlp->nlp_state, ndlp->nlp_rpi); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, + "0900 Cleanup node for NPort x%x " + "Data: x%x x%x x%x\n", + ndlp->nlp_DID, ndlp->nlp_flag, + ndlp->nlp_state, ndlp->nlp_rpi); lpfc_dequeue_node(vport, ndlp); /* cleanup any ndlp on mbox q waiting for reglogin cmpl */ @@ -2094,7 +2072,6 @@ lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, static struct lpfc_nodelist * __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) { - struct lpfc_hba *phba = vport->phba; struct lpfc_nodelist *ndlp; uint32_t data1; @@ -2104,20 +2081,18 @@ __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d (%d):0929 FIND node DID " - " Data: x%p x%x x%x x%x\n", - phba->brd_no, vport->vpi, - ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1); + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, + "0929 FIND node DID " + "Data: x%p x%x x%x x%x\n", + ndlp, ndlp->nlp_DID, + ndlp->nlp_flag, data1); return ndlp; } } /* FIND node did <did> NOT FOUND */ - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d (%d):0932 FIND node did x%x NOT FOUND.\n", - phba->brd_no, vport->vpi, did); + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, + "0932 FIND node did x%x NOT FOUND.\n", did); return NULL; } @@ -2208,7 +2183,7 @@ lpfc_disc_list_loopmap(struct lpfc_vport *vport) /* If cfg_scan_down is set, start from highest * ALPA (0xef) to lowest (0x1). */ - if (phba->cfg_scan_down) + if (vport->cfg_scan_down) index = j; else index = FC_MAXLOOP - j - 1; @@ -2309,12 +2284,11 @@ lpfc_disc_start(struct lpfc_vport *vport) vport->num_disc_nodes = 0; /* Start Discovery state <hba_state> */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0202 Start Discovery hba state x%x " - "Data: x%x x%x x%x\n", - phba->brd_no, vport->vpi, vport->port_state, - vport->fc_flag, vport->fc_plogi_cnt, - vport->fc_adisc_cnt); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0202 Start Discovery hba state x%x " + "Data: x%x x%x x%x\n", + vport->port_state, vport->fc_flag, vport->fc_plogi_cnt, + vport->fc_adisc_cnt); /* First do ADISCs - if any */ num_sent = lpfc_els_disc_adisc(vport); @@ -2532,10 +2506,8 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) * FAN */ /* FAN timeout */ - lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY, - "%d (%d):0221 FAN timeout\n", - phba->brd_no, vport->vpi); - + lpfc_printf_vlog(vport, KERN_WARNING, LOG_DISCOVERY, + "0221 FAN timeout\n"); /* Start discovery by sending FLOGI, clean up old rpis */ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { @@ -2562,10 +2534,9 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) case LPFC_FLOGI: /* port_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */ /* Initial FLOGI timeout */ - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0222 Initial %s timeout\n", - phba->brd_no, vport->vpi, - vport->vpi ? "FLOGI" : "FDISC"); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0222 Initial %s timeout\n", + vport->vpi ? "FLOGI" : "FDISC"); /* Assume no Fabric and go on with discovery. * Check for outstanding ELS FLOGI to abort. @@ -2581,11 +2552,9 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) case LPFC_FABRIC_CFG_LINK: /* hba_state is identically LPFC_FABRIC_CFG_LINK while waiting for NameServer login */ - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0223 Timeout while waiting for " - "NameServer login\n", - phba->brd_no, vport->vpi); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0223 Timeout while waiting for " + "NameServer login\n"); /* Next look for NameServer ndlp */ ndlp = lpfc_findnode_did(vport, NameServer_DID); if (ndlp) @@ -2596,11 +2565,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) case LPFC_NS_QRY: /* Check for wait for NameServer Rsp timeout */ - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0224 NameServer Query timeout " - "Data: x%x x%x\n", - phba->brd_no, vport->vpi, - vport->fc_ns_retry, LPFC_MAX_NS_RETRY); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0224 NameServer Query timeout " + "Data: x%x x%x\n", + vport->fc_ns_retry, LPFC_MAX_NS_RETRY); if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { /* Try it one more time */ @@ -2627,10 +2595,9 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) /* Setup and issue mailbox INITIALIZE LINK command */ initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!initlinkmbox) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0206 Device Discovery " - "completion error\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0206 Device Discovery " + "completion error\n"); phba->link_state = LPFC_HBA_ERROR; break; } @@ -2651,9 +2618,8 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) case LPFC_DISC_AUTH: /* Node Authentication timeout */ - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0227 Node Authentication timeout\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0227 Node Authentication timeout\n"); lpfc_disc_flush_list(vport); /* @@ -2670,11 +2636,10 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) case LPFC_VPORT_READY: if (vport->fc_flag & FC_RSCN_MODE) { - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0231 RSCN timeout Data: x%x " - "x%x\n", - phba->brd_no, vport->vpi, - vport->fc_ns_retry, LPFC_MAX_NS_RETRY); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0231 RSCN timeout Data: x%x " + "x%x\n", + vport->fc_ns_retry, LPFC_MAX_NS_RETRY); /* Cleanup any outstanding ELS commands */ lpfc_els_flush_cmd(vport); @@ -2685,20 +2650,17 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0229 Unexpected discovery timeout, " - "vport State x%x\n", - phba->brd_no, vport->vpi, vport->port_state); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0229 Unexpected discovery timeout, " + "vport State x%x\n", vport->port_state); break; } switch (phba->link_state) { case LPFC_CLEAR_LA: /* CLEAR LA timeout */ - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0228 CLEAR LA timeout\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0228 CLEAR LA timeout\n"); clrlaerr = 1; break; @@ -2709,10 +2671,9 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) case LPFC_LINK_DOWN: case LPFC_LINK_UP: case LPFC_HBA_ERROR: - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0230 Unexpected timeout, hba link " - "state x%x\n", - phba->brd_no, vport->vpi, phba->link_state); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0230 Unexpected timeout, hba link " + "state x%x\n", phba->link_state); clrlaerr = 1; break; @@ -2757,7 +2718,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) * fdmi-on=2 (supporting RPA/hostnmae) */ - if (phba->cfg_fdmi_on == 1) + if (vport->cfg_fdmi_on == 1) lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA); else mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60); @@ -2854,32 +2815,6 @@ lpfc_findnode_wwpn(struct lpfc_vport *vport, struct lpfc_name *wwpn) } void -lpfc_dev_loss_delay(unsigned long ptr) -{ - struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr; - struct lpfc_vport *vport = ndlp->vport; - struct lpfc_hba *phba = vport->phba; - struct lpfc_work_evt *evtp = &ndlp->dev_loss_evt; - unsigned long flags; - - evtp = &ndlp->dev_loss_evt; - - spin_lock_irqsave(&phba->hbalock, flags); - if (!list_empty(&evtp->evt_listp)) { - spin_unlock_irqrestore(&phba->hbalock, flags); - return; - } - - evtp->evt_arg1 = ndlp; - evtp->evt = LPFC_EVT_DEV_LOSS_DELAY; - list_add_tail(&evtp->evt_listp, &phba->work_list); - if (phba->work_wait) - lpfc_worker_wake_up(phba); - spin_unlock_irqrestore(&phba->hbalock, flags); - return; -} - -void lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint32_t did) { @@ -2902,7 +2837,7 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return; } -void +static void lpfc_nlp_release(struct kref *kref) { struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index c2fb59f595f..451accd5564 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -150,7 +150,11 @@ struct lpfc_sli_ct_request { struct gff_acc { uint8_t fbits[128]; } gff_acc; +#ifdef __BIG_ENDIAN_BITFIELD +#define FCP_TYPE_FEATURE_OFFSET 7 +#else /* __LITTLE_ENDIAN_BITFIELD */ #define FCP_TYPE_FEATURE_OFFSET 4 +#endif struct rff { uint32_t PortId; uint8_t reserved[2]; @@ -805,7 +809,7 @@ typedef struct _RNID { /* Structure is in Big Endian format */ } un; } RNID; -typedef struct _RPS { /* Structure is in Big Endian format */ +typedef struct _RPS { /* Structure is in Big Endian format */ union { uint32_t portNum; struct lpfc_name portName; @@ -823,7 +827,7 @@ typedef struct _RPS_RSP { /* Structure is in Big Endian format */ uint32_t crcCnt; } RPS_RSP; -typedef struct _RPL { /* Structure is in Big Endian format */ +typedef struct _RPL { /* Structure is in Big Endian format */ uint32_t maxsize; uint32_t index; } RPL; @@ -834,7 +838,7 @@ typedef struct _PORT_NUM_BLK { struct lpfc_name portName; } PORT_NUM_BLK; -typedef struct _RPL_RSP { /* Structure is in Big Endian format */ +typedef struct _RPL_RSP { /* Structure is in Big Endian format */ uint32_t listLen; uint32_t index; PORT_NUM_BLK port_num_blk; @@ -2613,8 +2617,8 @@ typedef union { LOAD_SM_VAR varLdSM; /* cmd = 1 (LOAD_SM) */ READ_NV_VAR varRDnvp; /* cmd = 2 (READ_NVPARMS) */ WRITE_NV_VAR varWTnvp; /* cmd = 3 (WRITE_NVPARMS) */ - BIU_DIAG_VAR varBIUdiag; /* cmd = 4 (RUN_BIU_DIAG) */ - INIT_LINK_VAR varInitLnk; /* cmd = 5 (INIT_LINK) */ + BIU_DIAG_VAR varBIUdiag; /* cmd = 4 (RUN_BIU_DIAG) */ + INIT_LINK_VAR varInitLnk; /* cmd = 5 (INIT_LINK) */ DOWN_LINK_VAR varDwnLnk; /* cmd = 6 (DOWN_LINK) */ CONFIG_LINK varCfgLnk; /* cmd = 7 (CONFIG_LINK) */ PART_SLIM_VAR varSlim; /* cmd = 8 (PART_SLIM) */ diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f81f85ee190..414350ab584 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -53,8 +53,6 @@ static struct scsi_transport_template *lpfc_transport_template = NULL; static struct scsi_transport_template *lpfc_vport_transport_template = NULL; static DEFINE_IDR(lpfc_hba_index); - - /************************************************************************/ /* */ /* lpfc_config_port_prep */ @@ -107,10 +105,9 @@ lpfc_config_port_prep(struct lpfc_hba *phba) if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, - "%d:0324 Config Port initialization " + "0324 Config Port initialization " "error, mbxCmd x%x READ_NVPARM, " "mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); mempool_free(pmb, phba->mbox_mem_pool); return -ERESTART; @@ -128,9 +125,8 @@ lpfc_config_port_prep(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0439 Adapter failed to init, mbxCmd x%x " + "0439 Adapter failed to init, mbxCmd x%x " "READ_REV, mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); mempool_free( pmb, phba->mbox_mem_pool); return -ERESTART; @@ -144,9 +140,8 @@ lpfc_config_port_prep(struct lpfc_hba *phba) if (mb->un.varRdRev.rr == 0) { vp->rev.rBit = 0; lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0440 Adapter failed to init, READ_REV has " - "missing revision information.\n", - phba->brd_no); + "0440 Adapter failed to init, READ_REV has " + "missing revision information.\n"); mempool_free(pmb, phba->mbox_mem_pool); return -ERESTART; } @@ -197,9 +192,8 @@ lpfc_config_port_prep(struct lpfc_hba *phba) if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0441 VPD not present on adapter, " + "0441 VPD not present on adapter, " "mbxCmd x%x DUMP VPD, mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); mb->un.varDmp.word_cnt = 0; } @@ -253,9 +247,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) pmb->vport = vport; if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0448 Adapter failed init, mbxCmd x%x " + "0448 Adapter failed init, mbxCmd x%x " "READ_SPARM mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); phba->link_state = LPFC_HBA_ERROR; mp = (struct lpfc_dmabuf *) pmb->context1; @@ -312,9 +305,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) pmb->vport = vport; if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0453 Adapter failed to init, mbxCmd x%x " + "0453 Adapter failed to init, mbxCmd x%x " "READ_CONFIG, mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); phba->link_state = LPFC_HBA_ERROR; mempool_free( pmb, phba->mbox_mem_pool); @@ -344,9 +336,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) && !(phba->lmt & LMT_10Gb))) { /* Reset link speed to auto */ lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT, - "%d:1302 Invalid speed for this board: " + "1302 Invalid speed for this board: " "Reset link speed to auto: x%x\n", - phba->brd_no, phba->cfg_link_speed); phba->cfg_link_speed = LINK_SPEED_AUTO; } @@ -402,9 +393,8 @@ lpfc_config_port_post(struct lpfc_hba *phba) lpfc_set_loopback_flag(phba); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0454 Adapter failed to init, mbxCmd x%x " + "0454 Adapter failed to init, mbxCmd x%x " "INIT_LINK, mbxStatus x%x\n", - phba->brd_no, mb->mbxCommand, mb->mbxStatus); /* Clear all interrupt enable conditions */ @@ -437,16 +427,11 @@ lpfc_config_port_post(struct lpfc_hba *phba) int lpfc_hba_down_prep(struct lpfc_hba *phba) { - struct lpfc_vport *vport = phba->pport; - /* Disable interrupts */ writel(0, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ - list_for_each_entry(vport, &phba->port_list, listentry) { - lpfc_cleanup_discovery_resources(vport); - } - + lpfc_cleanup_discovery_resources(phba->pport); return 0; } @@ -518,7 +503,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) mempool_free(pmboxq, phba->mbox_mem_pool); if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) && !(phba->link_state == LPFC_HBA_ERROR) && - !(phba->pport->fc_flag & FC_UNLOADING)) + !(phba->pport->load_flag & FC_UNLOADING)) mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL); return; @@ -532,7 +517,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) struct lpfc_sli *psli = &phba->sli; if ((phba->link_state == LPFC_HBA_ERROR) || - (phba->pport->fc_flag & FC_UNLOADING) || + (phba->pport->load_flag & FC_UNLOADING) || (phba->pport->fc_flag & FC_OFFLINE_MODE)) return; @@ -586,8 +571,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) * need to take the HBA offline. */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0459 Adapter heartbeat failure, taking " - "this port offline.\n", phba->brd_no); + "0459 Adapter heartbeat failure, taking " + "this port offline.\n"); spin_lock_irq(&phba->hbalock); psli->sli_flag &= ~LPFC_SLI2_ACTIVE; @@ -615,9 +600,10 @@ lpfc_handle_eratt(struct lpfc_hba *phba) struct lpfc_vport *vport = phba->pport; struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; - struct lpfc_vport *port_iterator; + struct lpfc_vport **vports; uint32_t event_data; struct Scsi_Host *shost; + int i; /* If the pci channel is offline, ignore possible errors, * since we cannot communicate with the pci card anyway. */ @@ -628,18 +614,21 @@ lpfc_handle_eratt(struct lpfc_hba *phba) phba->work_hs & HS_FFER5) { /* Re-establishing Link */ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, - "%d:1301 Re-establishing Link " + "1301 Re-establishing Link " "Data: x%x x%x x%x\n", - phba->brd_no, phba->work_hs, + phba->work_hs, phba->work_status[0], phba->work_status[1]); - list_for_each_entry(port_iterator, &phba->port_list, - listentry) { - shost = lpfc_shost_from_vport(port_iterator); - - spin_lock_irq(shost->host_lock); - port_iterator->fc_flag |= FC_ESTABLISH_LINK; - spin_unlock_irq(shost->host_lock); - } + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; + i < LPFC_MAX_VPORTS && vports[i] != NULL; + i++){ + shost = lpfc_shost_from_vport(vports[i]); + spin_lock_irq(shost->host_lock); + vports[i]->fc_flag |= FC_ESTABLISH_LINK; + spin_unlock_irq(shost->host_lock); + } + lpfc_destroy_vport_work_array(vports); spin_lock_irq(&phba->hbalock); psli->sli_flag &= ~LPFC_SLI2_ACTIVE; spin_unlock_irq(&phba->hbalock); @@ -673,9 +662,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba) * twice. This is the adapter hardware error path. */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0457 Adapter Hardware Error " + "0457 Adapter Hardware Error " "Data: x%x x%x x%x\n", - phba->brd_no, phba->work_hs, + phba->work_hs, phba->work_status[0], phba->work_status[1]); event_data = FC_REG_DUMP_EVENT; @@ -708,7 +697,6 @@ lpfc_handle_latt(struct lpfc_hba *phba) { struct lpfc_vport *vport = phba->pport; struct lpfc_sli *psli = &phba->sli; - struct lpfc_vport *port_iterator; LPFC_MBOXQ_t *pmb; volatile uint32_t control; struct lpfc_dmabuf *mp; @@ -729,8 +717,7 @@ lpfc_handle_latt(struct lpfc_hba *phba) rc = -EIO; /* Cleanup any outstanding ELS commands */ - list_for_each_entry(port_iterator, &phba->port_list, listentry) - lpfc_els_flush_cmd(port_iterator); + lpfc_els_flush_all_cmd(phba); psli->slistat.link_event++; lpfc_read_la(phba, pmb, mp); @@ -773,8 +760,7 @@ lpfc_handle_latt_err_exit: /* The other case is an error from issue_mbox */ if (rc == -ENOMEM) lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, - "%d:0300 READ_LA: no buffers\n", - phba->brd_no); + "0300 READ_LA: no buffers\n"); return; } @@ -799,8 +785,7 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len) /* Vital Product */ lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0455 Vital Product Data: x%x x%x x%x x%x\n", - phba->brd_no, + "0455 Vital Product Data: x%x x%x x%x x%x\n", (uint32_t) vpd[0], (uint32_t) vpd[1], (uint32_t) vpd[2], (uint32_t) vpd[3]); while (!finished && (index < (len - 4))) { @@ -1313,22 +1298,25 @@ static void lpfc_establish_link_tmo(unsigned long ptr) { struct lpfc_hba *phba = (struct lpfc_hba *) ptr; - struct lpfc_vport *vport = phba->pport; + struct lpfc_vport **vports; unsigned long iflag; + int i; /* Re-establishing Link, timer expired */ lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, - "%d:1300 Re-establishing Link, timer expired " + "1300 Re-establishing Link, timer expired " "Data: x%x x%x\n", - phba->brd_no, vport->fc_flag, - vport->port_state); - list_for_each_entry(vport, &phba->port_list, listentry) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - - spin_lock_irqsave(shost->host_lock, iflag); - vport->fc_flag &= ~FC_ESTABLISH_LINK; - spin_unlock_irqrestore(shost->host_lock, iflag); - } + phba->pport->fc_flag, phba->pport->port_state); + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { + struct Scsi_Host *shost; + shost = lpfc_shost_from_vport(vports[i]); + spin_lock_irqsave(shost->host_lock, iflag); + vports[i]->fc_flag &= ~FC_ESTABLISH_LINK; + spin_unlock_irqrestore(shost->host_lock, iflag); + } + lpfc_destroy_vport_work_array(vports); } void @@ -1343,12 +1331,9 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport) static void lpfc_stop_phba_timers(struct lpfc_hba *phba) { - struct lpfc_vport *vport; - del_timer_sync(&phba->fcp_poll_timer); del_timer_sync(&phba->fc_estabtmo); - list_for_each_entry(vport, &phba->port_list, listentry) - lpfc_stop_vport_timers(vport); + lpfc_stop_vport_timers(phba->pport); del_timer_sync(&phba->sli.mbox_tmo); del_timer_sync(&phba->fabric_block_timer); phba->hb_outstanding = 0; @@ -1360,6 +1345,8 @@ int lpfc_online(struct lpfc_hba *phba) { struct lpfc_vport *vport = phba->pport; + struct lpfc_vport **vports; + int i; if (!phba) return 0; @@ -1368,8 +1355,7 @@ lpfc_online(struct lpfc_hba *phba) return 0; lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "%d:0458 Bring Adapter online\n", - phba->brd_no); + "0458 Bring Adapter online\n"); lpfc_block_mgmt_io(phba); @@ -1383,14 +1369,18 @@ lpfc_online(struct lpfc_hba *phba) return 1; } - list_for_each_entry(vport, &phba->port_list, listentry) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - spin_lock_irq(shost->host_lock); - vport->fc_flag &= ~FC_OFFLINE_MODE; - if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) - vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; - spin_unlock_irq(shost->host_lock); - } + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { + struct Scsi_Host *shost; + shost = lpfc_shost_from_vport(vports[i]); + spin_lock_irq(shost->host_lock); + vports[i]->fc_flag &= ~FC_OFFLINE_MODE; + if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) + vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; + spin_unlock_irq(shost->host_lock); + } + lpfc_destroy_vport_work_array(vports); lpfc_unblock_mgmt_io(phba); return 0; @@ -1440,39 +1430,39 @@ lpfc_offline_prep(struct lpfc_hba * phba) void lpfc_offline(struct lpfc_hba *phba) { - struct lpfc_vport *vport = phba->pport; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - struct lpfc_vport *port_iterator; + struct Scsi_Host *shost; + struct lpfc_vport **vports; + int i; - if (vport->fc_flag & FC_OFFLINE_MODE) + if (phba->pport->fc_flag & FC_OFFLINE_MODE) return; /* stop all timers associated with this hba */ lpfc_stop_phba_timers(phba); - list_for_each_entry(port_iterator, &phba->port_list, listentry) { - port_iterator->work_port_events = 0; - } - + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) + lpfc_stop_vport_timers(vports[i]); + lpfc_destroy_vport_work_array(vports); lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, - "%d:0460 Bring Adapter offline\n", - phba->brd_no); - + "0460 Bring Adapter offline\n"); /* Bring down the SLI Layer and cleanup. The HBA is offline now. */ lpfc_sli_hba_down(phba); spin_lock_irq(&phba->hbalock); phba->work_ha = 0; - vport->fc_flag |= FC_OFFLINE_MODE; spin_unlock_irq(&phba->hbalock); - list_for_each_entry(port_iterator, &phba->port_list, listentry) { - shost = lpfc_shost_from_vport(port_iterator); - - lpfc_cleanup(port_iterator); - spin_lock_irq(shost->host_lock); - vport->work_port_events = 0; - vport->fc_flag |= FC_OFFLINE_MODE; - spin_unlock_irq(shost->host_lock); - } + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { + shost = lpfc_shost_from_vport(vports[i]); + lpfc_cleanup(vports[i]); + spin_lock_irq(shost->host_lock); + vports[i]->work_port_events = 0; + vports[i]->fc_flag |= FC_OFFLINE_MODE; + spin_unlock_irq(shost->host_lock); + } + lpfc_destroy_vport_work_array(vports); } /****************************************************************************** @@ -1509,15 +1499,19 @@ lpfc_scsi_free(struct lpfc_hba *phba) return 0; } - struct lpfc_vport * -lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport) +lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) { struct lpfc_vport *vport; struct Scsi_Host *shost; int error = 0; - shost = scsi_host_alloc(&lpfc_template, sizeof(struct lpfc_vport)); + if (dev != &phba->pcidev->dev) + shost = scsi_host_alloc(&lpfc_vport_template, + sizeof(struct lpfc_vport)); + else + shost = scsi_host_alloc(&lpfc_template, + sizeof(struct lpfc_vport)); if (!shost) goto out; @@ -1527,9 +1521,10 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport) vport->load_flag |= FC_LOADING; vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; + lpfc_get_vport_cfgparam(vport); shost->unique_id = instance; shost->max_id = LPFC_MAX_TARGET; - shost->max_lun = phba->cfg_max_luns; + shost->max_lun = vport->cfg_max_luns; shost->this_id = -1; shost->max_cmd_len = 16; /* @@ -1538,7 +1533,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport) * max xri value determined in hba setup. */ shost->can_queue = phba->cfg_hba_queue_depth - 10; - if (fc_vport != NULL) { + if (dev != &phba->pcidev->dev) { shost->transportt = lpfc_vport_transport_template; vport->port_type = LPFC_NPIV_PORT; } else { @@ -1562,15 +1557,13 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct fc_vport *fc_vport) vport->els_tmofunc.function = lpfc_els_timeout; vport->els_tmofunc.data = (unsigned long)vport; - if (fc_vport != NULL) { - error = scsi_add_host(shost, &fc_vport->dev); - } else { - error = scsi_add_host(shost, &phba->pcidev->dev); - } + error = scsi_add_host(shost, dev); if (error) goto out_put_shost; + spin_lock_irq(&phba->hbalock); list_add_tail(&vport->listentry, &phba->port_list); + spin_unlock_irq(&phba->hbalock); return vport; out_put_shost: @@ -1625,23 +1618,21 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) spin_lock_irq(shost->host_lock); - if (vport->fc_flag & FC_UNLOADING) { + if (vport->load_flag & FC_UNLOADING) { stat = 1; goto finished; } if (time >= 30 * HZ) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0461 Scanning longer than 30 " - "seconds. Continuing initialization\n", - phba->brd_no); + "0461 Scanning longer than 30 " + "seconds. Continuing initialization\n"); stat = 1; goto finished; } if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0465 Link down longer than 15 " - "seconds. Continuing initialization\n", - phba->brd_no); + "0465 Link down longer than 15 " + "seconds. Continuing initialization\n"); stat = 1; goto finished; } @@ -1704,7 +1695,7 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost) fc_host_max_npiv_vports(shost) = phba->max_vpi; spin_lock_irq(shost->host_lock); - vport->fc_flag &= ~FC_LOADING; + vport->load_flag &= ~FC_LOADING; spin_unlock_irq(shost->host_lock); } @@ -1716,9 +1707,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) struct lpfc_sli *psli; struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL; struct Scsi_Host *shost = NULL; + void *ptr; unsigned long bar0map_len, bar2map_len; int error = -ENODEV; - int i; + int i, hbq_count; uint16_t iotag; if (pci_enable_device(pdev)) @@ -1739,7 +1731,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_free_phba; INIT_LIST_HEAD(&phba->port_list); - INIT_LIST_HEAD(&phba->hbq_buffer_list); /* * Get all the module params for configuring this host and then * establish the host. @@ -1817,6 +1808,17 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) if (!phba->hbqslimp.virt) goto out_free_slim; + hbq_count = lpfc_sli_hbq_count(); + ptr = phba->hbqslimp.virt; + for (i = 0; i < hbq_count; ++i) { + phba->hbqs[i].hbq_virt = ptr; + INIT_LIST_HEAD(&phba->hbqs[i].hbq_buffer_list); + ptr += (lpfc_hbq_defs[i]->entry_count * + sizeof(struct lpfc_hbq_entry)); + } + phba->hbqs[LPFC_ELS_HBQ].hbq_alloc_buffer = lpfc_els_hbq_alloc; + phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer = lpfc_els_hbq_free; + memset(phba->hbqslimp.virt, 0, lpfc_sli_hbq_size()); /* Initialize the SLI Layer to run with lpfc HBAs. */ @@ -1830,7 +1832,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) /* Initialize and populate the iocb list per host. */ INIT_LIST_HEAD(&phba->lpfc_iocb_list); for (i = 0; i < LPFC_IOCB_LIST_CNT; i++) { - iocbq_entry = kmalloc(sizeof(struct lpfc_iocbq), GFP_KERNEL); + iocbq_entry = kzalloc(sizeof(struct lpfc_iocbq), GFP_KERNEL); if (iocbq_entry == NULL) { printk(KERN_ERR "%s: only allocated %d iocbs of " "expected %d count. Unloading driver.\n", @@ -1839,7 +1841,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_free_iocbq; } - memset(iocbq_entry, 0, sizeof(struct lpfc_iocbq)); iotag = lpfc_sli_next_iotag(phba, iocbq_entry); if (iotag == 0) { kfree (iocbq_entry); @@ -1881,7 +1882,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) /* Initialize list of fabric iocbs */ INIT_LIST_HEAD(&phba->fabric_iocb_list); - vport = lpfc_create_port(phba, phba->brd_no, NULL); + vport = lpfc_create_port(phba, phba->brd_no, &phba->pcidev->dev); if (!vport) goto out_kthread_stop; @@ -1893,18 +1894,19 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) if (phba->cfg_use_msi) { error = pci_enable_msi(phba->pcidev); - if (error) - lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "%d:0452 " - "Enable MSI failed, continuing with " - "IRQ\n", phba->brd_no); + if (!error) + phba->using_msi = 1; + else + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "0452 Enable MSI failed, continuing " + "with IRQ\n"); } error = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED, LPFC_DRIVER_NAME, phba); if (error) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0451 Enable interrupt handler failed\n", - phba->brd_no); + "0451 Enable interrupt handler failed\n"); goto out_disable_msi; } @@ -1941,14 +1943,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) out_remove_device: lpfc_free_sysfs_attr(vport); spin_lock_irq(shost->host_lock); - vport->fc_flag |= FC_UNLOADING; + vport->load_flag |= FC_UNLOADING; spin_unlock_irq(shost->host_lock); out_free_irq: lpfc_stop_phba_timers(phba); phba->pport->work_port_events = 0; free_irq(phba->pcidev->irq, phba); out_disable_msi: - pci_disable_msi(phba->pcidev); + if (phba->using_msi) + pci_disable_msi(phba->pcidev); destroy_port(vport); out_kthread_stop: kthread_stop(phba->worker_thread); @@ -1990,16 +1993,15 @@ lpfc_pci_remove_one(struct pci_dev *pdev) struct Scsi_Host *shost = pci_get_drvdata(pdev); struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; - struct lpfc_vport *port_iterator; - list_for_each_entry(port_iterator, &phba->port_list, listentry) - port_iterator->load_flag |= FC_UNLOADING; + spin_lock_irq(&phba->hbalock); + vport->load_flag |= FC_UNLOADING; + spin_unlock_irq(&phba->hbalock); kfree(vport->vname); lpfc_free_sysfs_attr(vport); fc_remove_host(shost); scsi_remove_host(shost); - /* * Bring down the SLI Layer. This step disable all interrupts, * clears the rings, discards all mailbox commands, and resets @@ -2013,7 +2015,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) list_del_init(&vport->listentry); spin_unlock_irq(&phba->hbalock); - lpfc_debugfs_terminate(vport); lpfc_cleanup(vport); @@ -2021,7 +2022,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) /* Release the irq reservation */ free_irq(phba->pcidev->irq, phba); - pci_disable_msi(phba->pcidev); + if (phba->using_msi) + pci_disable_msi(phba->pcidev); pci_set_drvdata(pdev, NULL); scsi_host_put(shost); @@ -2063,8 +2065,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; @@ -2080,6 +2082,11 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, pring = &psli->ring[psli->fcp_ring]; lpfc_sli_abort_iocb_ring(phba, pring); + /* Release the irq reservation */ + free_irq(phba->pcidev->irq, phba); + if (phba->using_msi) + pci_disable_msi(phba->pcidev); + /* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET; } @@ -2092,8 +2099,8 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, */ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; struct lpfc_sli *psli = &phba->sli; int bars = pci_select_bars(pdev, IORESOURCE_MEM); @@ -2107,9 +2114,9 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) pci_set_master(pdev); /* Re-establishing Link */ - spin_lock_irq(host->host_lock); + spin_lock_irq(shost->host_lock); phba->pport->fc_flag |= FC_ESTABLISH_LINK; - spin_unlock_irq(host->host_lock); + spin_unlock_irq(shost->host_lock); spin_lock_irq(&phba->hbalock); psli->sli_flag &= ~LPFC_SLI2_ACTIVE; @@ -2132,8 +2139,8 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) */ static void lpfc_io_resume(struct pci_dev *pdev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata; + struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; if (lpfc_online(phba) == 0) { mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index 8a6ceffeabc..626e4d87872 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h @@ -33,6 +33,12 @@ #define LOG_VPORT 0x4000 /* NPIV events */ #define LOG_ALL_MSG 0xffff /* LOG all messages */ +#define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \ + { if (((mask) &(vport)->cfg_log_verbose) || (level[1] <= '3')) \ + dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \ + fmt, (vport)->phba->brd_no, vport->vpi, ##arg); } + #define lpfc_printf_log(phba, level, mask, fmt, arg...) \ - { if (((mask) &(phba)->cfg_log_verbose) || (level[1] <= '3')) \ - dev_printk(level, &((phba)->pcidev)->dev, fmt, ##arg); } + { if (((mask) &(phba)->pport->cfg_log_verbose) || (level[1] <= '3')) \ + dev_printk(level, &((phba)->pcidev)->dev, "%d:" \ + fmt, phba->brd_no, ##arg); } diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 8f42fbfdd29..a592733664e 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -275,11 +275,8 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi) kfree(mp); mb->mbxCommand = MBX_READ_SPARM64; /* READ_SPARAM: no buffers */ - lpfc_printf_log(phba, - KERN_WARNING, - LOG_MBOX, - "%d:0301 READ_SPARAM: no buffers\n", - phba->brd_no); + lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, + "0301 READ_SPARAM: no buffers\n"); return (1); } INIT_LIST_HEAD(&mp->list); @@ -378,9 +375,8 @@ lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, mb->mbxCommand = MBX_REG_LOGIN64; /* REG_LOGIN: no buffers */ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, - "%d (%d):0302 REG_LOGIN: no buffers, DID x%x, " - "flag x%x\n", - phba->brd_no, vpi, did, flag); + "0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, " + "flag x%x\n", vpi, did, flag); return (1); } INIT_LIST_HEAD(&mp->list); @@ -564,7 +560,8 @@ lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb, } void -lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc, +lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id, + struct lpfc_hbq_init *hbq_desc, uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb) { int i; @@ -572,6 +569,7 @@ lpfc_config_hbq(struct lpfc_hba *phba, struct lpfc_hbq_init *hbq_desc, struct config_hbq_var *hbqmb = &mb->un.varCfgHbq; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); + hbqmb->hbqId = id; hbqmb->entry_count = hbq_desc->entry_count; /* # entries in HBQ */ hbqmb->recvNotify = hbq_desc->rn; /* Receive * Notification */ @@ -691,8 +689,8 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ - mb->un.varCfgPort.max_hbq = 1; /* Requesting 2 HBQs */ - if (phba->max_vpi && phba->cfg_npiv_enable && + mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count(); + if (phba->max_vpi && phba->cfg_enable_npiv && phba->vpd.sli3Feat.cmv) { mb->un.varCfgPort.max_vpi = phba->max_vpi; mb->un.varCfgPort.cmv = 1; diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 3594c469494..43c3b8a0d76 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -231,21 +231,34 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) return; } -void * -lpfc_hbq_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) +struct hbq_dmabuf * +lpfc_els_hbq_alloc(struct lpfc_hba *phba) { - void *ret; - ret = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_ATOMIC, handle); - return ret; + struct hbq_dmabuf *hbqbp; + + hbqbp = kmalloc(sizeof(struct hbq_dmabuf), GFP_KERNEL); + if (!hbqbp) + return NULL; + + hbqbp->dbuf.virt = pci_pool_alloc(phba->lpfc_hbq_pool, GFP_KERNEL, + &hbqbp->dbuf.phys); + if (!hbqbp->dbuf.virt) { + kfree(hbqbp); + return NULL; + } + hbqbp->size = LPFC_BPL_SIZE; + return hbqbp; } void -lpfc_hbq_free(struct lpfc_hba *phba, void *virt, dma_addr_t dma) +lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp) { - pci_pool_free(phba->lpfc_hbq_pool, virt, dma); + pci_pool_free(phba->lpfc_hbq_pool, hbqbp->dbuf.virt, hbqbp->dbuf.phys); + kfree(hbqbp); return; } +/* This is ONLY called for the LPFC_ELS_HBQ */ void lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) { @@ -254,9 +267,8 @@ lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); if (hbq_entry->tag == -1) { - lpfc_hbq_free(phba, hbq_entry->dbuf.virt, - hbq_entry->dbuf.phys); - kfree(hbq_entry); + (phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer) + (phba, hbq_entry); } else { lpfc_sli_free_hbq(phba, hbq_entry); } diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index bca2f5c9b4b..880af0cd463 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -133,15 +133,15 @@ lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name)); return 1; bad_service_param: - lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0207 Device %x " - "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent " - "invalid service parameters. Ignoring device.\n", - vport->phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID, - sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1], - sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3], - sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5], - sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0207 Device %x " + "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent " + "invalid service parameters. Ignoring device.\n", + ndlp->nlp_DID, + sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1], + sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3], + sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5], + sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]); return 0; } @@ -194,11 +194,11 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) IOCB_t *cmd; /* Abort outstanding I/O on NPort <nlp_DID> */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0205 Abort outstanding I/O on NPort x%x " - "Data: x%x x%x x%x\n", - phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); + lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY, + "0205 Abort outstanding I/O on NPort x%x " + "Data: x%x x%x x%x\n", + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi); lpfc_fabric_abort_nport(ndlp); @@ -298,13 +298,12 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, icmd = &cmdiocb->iocb; /* PLOGI chkparm OK */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, - ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, - ndlp->nlp_rpi); + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n", + ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, + ndlp->nlp_rpi); - if (phba->cfg_fcp_class == 2 && sp->cls2.classValid) + if (vport->cfg_fcp_class == 2 && sp->cls2.classValid) ndlp->nlp_fcp_info |= CLASS2; else ndlp->nlp_fcp_info |= CLASS3; @@ -330,7 +329,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, case NLP_STE_PRLI_ISSUE: case NLP_STE_UNMAPPED_NODE: case NLP_STE_MAPPED_NODE: - lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); return 1; } @@ -392,7 +391,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } if ((vport->port_type == LPFC_NPIV_PORT && - phba->cfg_vport_restrict_login)) { + vport->cfg_restrict_login)) { /* In order to preserve RPIs, we want to cleanup * the default RPI the firmware created to rcv @@ -408,7 +407,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp, mbox); return 1; } - lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); return 1; out: @@ -452,7 +451,7 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp); } else { lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, - NULL, 0); + NULL); } return 1; } @@ -489,9 +488,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_flag |= NLP_LOGO_ACC; spin_unlock_irq(shost->host_lock); if (els_cmd == ELS_CMD_PRLO) - lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); else - lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); if (!(ndlp->nlp_type & NLP_FABRIC) || (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { @@ -564,10 +563,14 @@ static uint32_t lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - struct lpfc_hba *phba = vport->phba; + + if (!ndlp->nlp_rpi) { + ndlp->nlp_flag &= ~NLP_NPR_ADISC; + return 0; + } /* Check config parameter use-adisc or FCP-2 */ - if ((phba->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || + if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_NPR_ADISC; @@ -583,12 +586,11 @@ static uint32_t lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0253 Illegal State Transition: node x%x " - "event x%x, state x%x Data: x%x x%x\n", - vport->phba->brd_no, vport->vpi, - ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, - ndlp->nlp_flag); + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0253 Illegal State Transition: node x%x " + "event x%x, state x%x Data: x%x x%x\n", + ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, + ndlp->nlp_flag); return ndlp->nlp_state; } @@ -630,7 +632,7 @@ lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_LOGO_ACC; spin_unlock_irq(shost->host_lock); - lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); return ndlp->nlp_state; @@ -726,7 +728,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, lpfc_els_abort(phba, ndlp); if (evt == NLP_EVT_RCV_LOGO) { - lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); } else { lpfc_issue_els_logo(vport, ndlp, 0); } @@ -778,16 +780,12 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3)) goto out; - /* PLOGI chkparm OK */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (%d):0121 PLOGI chkparm OK " - "Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, - ndlp->nlp_DID, ndlp->nlp_state, - ndlp->nlp_flag, ndlp->nlp_rpi); - - if (phba->cfg_fcp_class == 2 && (sp->cls2.classValid)) + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0121 PLOGI chkparm OK Data: x%x x%x x%x x%x\n", + ndlp->nlp_DID, ndlp->nlp_state, + ndlp->nlp_flag, ndlp->nlp_rpi); + if (vport->cfg_fcp_class == 2 && (sp->cls2.classValid)) ndlp->nlp_fcp_info |= CLASS2; else ndlp->nlp_fcp_info |= CLASS3; @@ -806,10 +804,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) { - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0133 PLOGI: no memory for reg_login " + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0133 PLOGI: no memory for reg_login " "Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, ndlp->nlp_rpi); goto out; @@ -844,30 +841,27 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, kfree(mp); mempool_free(mbox, phba->mbox_mem_pool); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0134 PLOGI: cannot issue reg_login " - "Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, - ndlp->nlp_DID, ndlp->nlp_state, - ndlp->nlp_flag, ndlp->nlp_rpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0134 PLOGI: cannot issue reg_login " + "Data: x%x x%x x%x x%x\n", + ndlp->nlp_DID, ndlp->nlp_state, + ndlp->nlp_flag, ndlp->nlp_rpi); } else { mempool_free(mbox, phba->mbox_mem_pool); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0135 PLOGI: cannot format reg_login " - "Data: x%x x%x x%x x%x\n", - phba->brd_no, vport->vpi, - ndlp->nlp_DID, ndlp->nlp_state, - ndlp->nlp_flag, ndlp->nlp_rpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0135 PLOGI: cannot format reg_login " + "Data: x%x x%x x%x x%x\n", + ndlp->nlp_DID, ndlp->nlp_state, + ndlp->nlp_flag, ndlp->nlp_rpi); } out: if (ndlp->nlp_DID == NameServer_DID) { lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0261 Cannot Register NameServer login\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0261 Cannot Register NameServer login\n"); } /* Free this node since the driver cannot login or has the wrong @@ -1178,7 +1172,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb; cmdiocb = (struct lpfc_iocbq *) arg; - lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); return ndlp->nlp_state; } @@ -1189,19 +1183,15 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, uint32_t evt) { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - struct lpfc_hba *phba = vport->phba; LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg; MAILBOX_t *mb = &pmb->mb; uint32_t did = mb->un.varWords[1]; if (mb->mbxStatus) { /* RegLogin failed */ - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d (%d):0246 RegLogin failed Data: x%x x%x " - "x%x\n", - phba->brd_no, vport->vpi, + lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, + "0246 RegLogin failed Data: x%x x%x x%x\n", did, mb->mbxStatus, vport->port_state); - /* * If RegLogin failed due to lack of HBA resources do not * retry discovery. @@ -1337,7 +1327,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, { struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; - lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); return ndlp->nlp_state; } @@ -1358,7 +1348,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, irsp = &rspiocb->iocb; if (irsp->ulpStatus) { if ((vport->port_type == LPFC_NPIV_PORT) && - phba->cfg_vport_restrict_login) { + vport->cfg_restrict_login) { goto out; } ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; @@ -1380,7 +1370,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } if (!(ndlp->nlp_type & NLP_FCP_TARGET) && (vport->port_type == LPFC_NPIV_PORT) && - phba->cfg_vport_restrict_login) { + vport->cfg_restrict_login) { out: spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_TARGET_REMOVE; @@ -1529,7 +1519,7 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, { struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; - lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); return ndlp->nlp_state; } @@ -1600,8 +1590,8 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; /* flush the target */ - lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], - ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); + lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], + ndlp->nlp_sid, 0, LPFC_CTX_TGT); /* Treat like rcv logo */ lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); @@ -1734,7 +1724,7 @@ lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_flag |= NLP_LOGO_ACC; spin_unlock_irq(shost->host_lock); - lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) { mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); @@ -2047,7 +2037,6 @@ int lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct lpfc_hba *phba = vport->phba; uint32_t cur_state, rc; uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t); @@ -2056,11 +2045,10 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, cur_state = ndlp->nlp_state; /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0211 DSM in event x%x on NPort x%x in " - "state %d Data: x%x\n", - phba->brd_no, vport->vpi, - evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0211 DSM in event x%x on NPort x%x in " + "state %d Data: x%x\n", + evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM, "DSM in: evt:%d ste:%d did:x%x", @@ -2070,11 +2058,9 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, rc = (func) (vport, ndlp, arg, evt); /* DSM out state <rc> on NPort <nlp_DID> */ - lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d (%d):0212 DSM out state %d on NPort x%x " - "Data: x%x\n", - phba->brd_no, vport->vpi, - rc, ndlp->nlp_DID, ndlp->nlp_flag); + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "0212 DSM out state %d on NPort x%x Data: x%x\n", + rc, ndlp->nlp_DID, ndlp->nlp_flag); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM, "DSM out: ste:%d did:x%x flg:x%x", diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 8f45bbc4212..17d7dc05149 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -84,22 +84,21 @@ lpfc_adjust_queue_depth(struct lpfc_hba *phba) * SCSI command completion. */ static inline void -lpfc_rampup_queue_depth(struct lpfc_hba *phba, +lpfc_rampup_queue_depth(struct lpfc_vport *vport, struct scsi_device *sdev) { unsigned long flags; + struct lpfc_hba *phba = vport->phba; atomic_inc(&phba->num_cmd_success); - if (phba->cfg_lun_queue_depth <= sdev->queue_depth) + if (vport->cfg_lun_queue_depth <= sdev->queue_depth) return; - spin_lock_irqsave(&phba->hbalock, flags); if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) || ((phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL ) > jiffies)) { spin_unlock_irqrestore(&phba->hbalock, flags); return; } - phba->last_ramp_up_time = jiffies; spin_unlock_irqrestore(&phba->hbalock, flags); @@ -119,43 +118,40 @@ lpfc_rampup_queue_depth(struct lpfc_hba *phba, void lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) { - struct lpfc_vport *vport; - struct Scsi_Host *host; + struct lpfc_vport **vports; + struct Scsi_Host *shost; struct scsi_device *sdev; unsigned long new_queue_depth; unsigned long num_rsrc_err, num_cmd_success; + int i; num_rsrc_err = atomic_read(&phba->num_rsrc_err); num_cmd_success = atomic_read(&phba->num_cmd_success); - spin_lock_irq(&phba->hbalock); - list_for_each_entry(vport, &phba->port_list, listentry) { - host = lpfc_shost_from_vport(vport); - if (!scsi_host_get(host)) - continue; - - spin_unlock_irq(&phba->hbalock); - - shost_for_each_device(sdev, host) { - new_queue_depth = sdev->queue_depth * num_rsrc_err / - (num_rsrc_err + num_cmd_success); - if (!new_queue_depth) - new_queue_depth = sdev->queue_depth - 1; - else + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { + shost = lpfc_shost_from_vport(vports[i]); + shost_for_each_device(sdev, shost) { new_queue_depth = - sdev->queue_depth - new_queue_depth; - - if (sdev->ordered_tags) - scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, - new_queue_depth); - else - scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, - new_queue_depth); + sdev->queue_depth * num_rsrc_err / + (num_rsrc_err + num_cmd_success); + if (!new_queue_depth) + new_queue_depth = sdev->queue_depth - 1; + else + new_queue_depth = sdev->queue_depth - + new_queue_depth; + if (sdev->ordered_tags) + scsi_adjust_queue_depth(sdev, + MSG_ORDERED_TAG, + new_queue_depth); + else + scsi_adjust_queue_depth(sdev, + MSG_SIMPLE_TAG, + new_queue_depth); + } } - spin_lock_irq(&phba->hbalock); - scsi_host_put(host); - } - spin_unlock_irq(&phba->hbalock); + lpfc_destroy_vport_work_array(vports); atomic_set(&phba->num_rsrc_err, 0); atomic_set(&phba->num_cmd_success, 0); } @@ -163,29 +159,27 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) void lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) { - struct lpfc_vport *vport; - struct Scsi_Host *host; + struct lpfc_vport **vports; + struct Scsi_Host *shost; struct scsi_device *sdev; - - spin_lock_irq(&phba->hbalock); - list_for_each_entry(vport, &phba->port_list, listentry) { - host = lpfc_shost_from_vport(vport); - if (!scsi_host_get(host)) - continue; - - spin_unlock_irq(&phba->hbalock); - shost_for_each_device(sdev, host) { - if (sdev->ordered_tags) - scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, - sdev->queue_depth+1); - else - scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, - sdev->queue_depth+1); + int i; + + vports = lpfc_create_vport_work_array(phba); + if (vports != NULL) + for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) { + shost = lpfc_shost_from_vport(vports[i]); + shost_for_each_device(sdev, shost) { + if (sdev->ordered_tags) + scsi_adjust_queue_depth(sdev, + MSG_ORDERED_TAG, + sdev->queue_depth+1); + else + scsi_adjust_queue_depth(sdev, + MSG_SIMPLE_TAG, + sdev->queue_depth+1); + } } - spin_lock_irq(&phba->hbalock); - scsi_host_put(host); - } - spin_unlock_irq(&phba->hbalock); + lpfc_destroy_vport_work_array(vports); atomic_set(&phba->num_rsrc_err, 0); atomic_set(&phba->num_cmd_success, 0); } @@ -411,9 +405,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, struct scsi_cmnd *cmnd = lpfc_cmd->pCmd; struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd; struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; - struct lpfc_hba *phba = vport->phba; uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm; - uint32_t vpi = vport->vpi; uint32_t resp_info = fcprsp->rspStatus2; uint32_t scsi_status = fcprsp->rspStatus3; uint32_t *lp; @@ -445,15 +437,15 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, if (!scsi_status && (resp_info & RESID_UNDER)) logit = LOG_FCP; - lpfc_printf_log(phba, KERN_WARNING, logit, - "%d (%d):0730 FCP command x%x failed: x%x SNS x%x x%x " - "Data: x%x x%x x%x x%x x%x\n", - phba->brd_no, vpi, cmnd->cmnd[0], scsi_status, - be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info, - be32_to_cpu(fcprsp->rspResId), - be32_to_cpu(fcprsp->rspSnsLen), - be32_to_cpu(fcprsp->rspRspLen), - fcprsp->rspInfo3); + lpfc_printf_vlog(vport, KERN_WARNING, logit, + "0730 FCP command x%x failed: x%x SNS x%x x%x " + "Data: x%x x%x x%x x%x x%x\n", + cmnd->cmnd[0], scsi_status, + be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info, + be32_to_cpu(fcprsp->rspResId), + be32_to_cpu(fcprsp->rspSnsLen), + be32_to_cpu(fcprsp->rspRspLen), + fcprsp->rspInfo3); if (resp_info & RSP_LEN_VALID) { rsplen = be32_to_cpu(fcprsp->rspRspLen); @@ -468,12 +460,12 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, if (resp_info & RESID_UNDER) { scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId)); - lpfc_printf_log(phba, KERN_INFO, LOG_FCP, - "%d (%d):0716 FCP Read Underrun, expected %d, " - "residual %d Data: x%x x%x x%x\n", - phba->brd_no, vpi, be32_to_cpu(fcpcmd->fcpDl), - scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0], - cmnd->underflow); + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "0716 FCP Read Underrun, expected %d, " + "residual %d Data: x%x x%x x%x\n", + be32_to_cpu(fcpcmd->fcpDl), + scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0], + cmnd->underflow); /* * If there is an under run check if under run reported by @@ -483,14 +475,13 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) && fcpi_parm && (scsi_get_resid(cmnd) != fcpi_parm)) { - lpfc_printf_log(phba, KERN_WARNING, - LOG_FCP | LOG_FCP_ERROR, - "%d (%d):0735 FCP Read Check Error " - "and Underrun Data: x%x x%x x%x x%x\n", - phba->brd_no, vpi, - be32_to_cpu(fcpcmd->fcpDl), - scsi_get_resid(cmnd), fcpi_parm, - cmnd->cmnd[0]); + lpfc_printf_vlog(vport, KERN_WARNING, + LOG_FCP | LOG_FCP_ERROR, + "0735 FCP Read Check Error " + "and Underrun Data: x%x x%x x%x x%x\n", + be32_to_cpu(fcpcmd->fcpDl), + scsi_get_resid(cmnd), fcpi_parm, + cmnd->cmnd[0]); scsi_set_resid(cmnd, scsi_bufflen(cmnd)); host_status = DID_ERROR; } @@ -504,21 +495,19 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, (scsi_status == SAM_STAT_GOOD) && (scsi_bufflen(cmnd) - scsi_get_resid(cmnd) < cmnd->underflow)) { - lpfc_printf_log(phba, KERN_INFO, LOG_FCP, - "%d (%d):0717 FCP command x%x residual " - "underrun converted to error " - "Data: x%x x%x x%x\n", - phba->brd_no, vpi, cmnd->cmnd[0], - scsi_bufflen(cmnd), - scsi_get_resid(cmnd), cmnd->underflow); + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "0717 FCP command x%x residual " + "underrun converted to error " + "Data: x%x x%x x%x\n", + cmnd->cmnd[0], scsi_bufflen(cmnd), + scsi_get_resid(cmnd), cmnd->underflow); host_status = DID_ERROR; } } else if (resp_info & RESID_OVER) { - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, - "%d (%d):0720 FCP command x%x residual " - "overrun error. Data: x%x x%x \n", - phba->brd_no, vpi, cmnd->cmnd[0], - scsi_bufflen(cmnd), scsi_get_resid(cmnd)); + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, + "0720 FCP command x%x residual overrun error. " + "Data: x%x x%x \n", cmnd->cmnd[0], + scsi_bufflen(cmnd), scsi_get_resid(cmnd)); host_status = DID_ERROR; /* @@ -527,13 +516,12 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, */ } else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm && (cmnd->sc_data_direction == DMA_FROM_DEVICE)) { - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR, - "%d (%d):0734 FCP Read Check Error Data: " - "x%x x%x x%x x%x\n", - phba->brd_no, vpi, - be32_to_cpu(fcpcmd->fcpDl), - be32_to_cpu(fcprsp->rspResId), - fcpi_parm, cmnd->cmnd[0]); + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR, + "0734 FCP Read Check Error Data: " + "x%x x%x x%x x%x\n", + be32_to_cpu(fcpcmd->fcpDl), + be32_to_cpu(fcprsp->rspResId), + fcpi_parm, cmnd->cmnd[0]); host_status = DID_ERROR; scsi_set_resid(cmnd, scsi_bufflen(cmnd)); } @@ -552,9 +540,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, struct lpfc_rport_data *rdata = lpfc_cmd->rdata; struct lpfc_nodelist *pnode = rdata->pnode; struct scsi_cmnd *cmd = lpfc_cmd->pCmd; - uint32_t vpi = (lpfc_cmd->cur_iocbq.vport - ? lpfc_cmd->cur_iocbq.vport->vpi - : 0); int result; struct scsi_device *sdev, *tmp_sdev; int depth = 0; @@ -569,15 +554,15 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, else if (lpfc_cmd->status >= IOSTAT_CNT) lpfc_cmd->status = IOSTAT_DEFAULT; - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, - "%d (%d):0729 FCP cmd x%x failed <%d/%d> " - "status: x%x result: x%x Data: x%x x%x\n", - phba->brd_no, vpi, cmd->cmnd[0], - cmd->device ? cmd->device->id : 0xffff, - cmd->device ? cmd->device->lun : 0xffff, - lpfc_cmd->status, lpfc_cmd->result, - pIocbOut->iocb.ulpContext, - lpfc_cmd->cur_iocbq.iocb.ulpIoTag); + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, + "0729 FCP cmd x%x failed <%d/%d> " + "status: x%x result: x%x Data: x%x x%x\n", + cmd->cmnd[0], + cmd->device ? cmd->device->id : 0xffff, + cmd->device ? cmd->device->lun : 0xffff, + lpfc_cmd->status, lpfc_cmd->result, + pIocbOut->iocb.ulpContext, + lpfc_cmd->cur_iocbq.iocb.ulpIoTag); switch (lpfc_cmd->status) { case IOSTAT_FCP_RSP_ERROR: @@ -610,13 +595,12 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) { uint32_t *lp = (uint32_t *)cmd->sense_buffer; - lpfc_printf_log(phba, KERN_INFO, LOG_FCP, - "%d (%d):0710 Iodone <%d/%d> cmd %p, error " - "x%x SNS x%x x%x Data: x%x x%x\n", - phba->brd_no, vpi, cmd->device->id, - cmd->device->lun, cmd, cmd->result, - *lp, *(lp + 3), cmd->retries, - scsi_get_resid(cmd)); + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "0710 Iodone <%d/%d> cmd %p, error " + "x%x SNS x%x x%x Data: x%x x%x\n", + cmd->device->id, cmd->device->lun, cmd, + cmd->result, *lp, *(lp + 3), cmd->retries, + scsi_get_resid(cmd)); } result = cmd->result; @@ -631,16 +615,16 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, if (!result) - lpfc_rampup_queue_depth(phba, sdev); + lpfc_rampup_queue_depth(vport, sdev); if (!result && pnode != NULL && ((jiffies - pnode->last_ramp_up_time) > LPFC_Q_RAMP_UP_INTERVAL * HZ) && ((jiffies - pnode->last_q_full_time) > LPFC_Q_RAMP_UP_INTERVAL * HZ) && - (phba->cfg_lun_queue_depth > sdev->queue_depth)) { + (vport->cfg_lun_queue_depth > sdev->queue_depth)) { shost_for_each_device(tmp_sdev, sdev->host) { - if (phba->cfg_lun_queue_depth > tmp_sdev->queue_depth) { + if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){ if (tmp_sdev->id != sdev->id) continue; if (tmp_sdev->ordered_tags) @@ -680,10 +664,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, depth = sdev->host->cmd_per_lun; if (depth) { - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, - "%d (%d):0711 detected queue full - " - "lun queue depth adjusted to %d.\n", - phba->brd_no, vpi, depth); + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, + "0711 detected queue full - lun queue " + "depth adjusted to %d.\n", depth); } } @@ -853,12 +836,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport, return FAILED; /* Issue Target Reset to TGT <num> */ - lpfc_printf_log(phba, KERN_INFO, LOG_FCP, - "%d (%d):0702 Issue Target Reset to TGT %d " - "Data: x%x x%x\n", - phba->brd_no, vport->vpi, tgt_id, - rdata->pnode->nlp_rpi, rdata->pnode->nlp_flag); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "0702 Issue Target Reset to TGT %d Data: x%x x%x\n", + tgt_id, rdata->pnode->nlp_rpi, rdata->pnode->nlp_flag); ret = lpfc_sli_issue_iocb_wait(phba, &phba->sli.ring[phba->sli.fcp_ring], iocbq, iocbqrsp, lpfc_cmd->timeout); @@ -965,10 +945,9 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) if (lpfc_cmd == NULL) { lpfc_adjust_queue_depth(phba); - lpfc_printf_log(phba, KERN_INFO, LOG_FCP, - "%d (%d):0707 driver's buffer pool is empty, " - "IO busied\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "0707 driver's buffer pool is empty, " + "IO busied\n"); goto out_host_busy; } @@ -1103,28 +1082,25 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) schedule_timeout_uninterruptible(LPFC_ABORT_WAIT * HZ); if (++loop_count - > (2 * phba->cfg_devloss_tmo)/LPFC_ABORT_WAIT) + > (2 * vport->cfg_devloss_tmo)/LPFC_ABORT_WAIT) break; } if (lpfc_cmd->pCmd == cmnd) { ret = FAILED; - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d (%d):0748 abort handler timed out waiting " - "for abort to complete: ret %#x, ID %d, " - "LUN %d, snum %#lx\n", - phba->brd_no, vport->vpi, ret, - cmnd->device->id, cmnd->device->lun, - cmnd->serial_number); + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0748 abort handler timed out waiting " + "for abort to complete: ret %#x, ID %d, " + "LUN %d, snum %#lx\n", + ret, cmnd->device->id, cmnd->device->lun, + cmnd->serial_number); } out: - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, - "%d (%d):0749 SCSI Layer I/O Abort Request " - "Status x%x ID %d LUN %d snum %#lx\n", - phba->brd_no, vport->vpi, ret, cmnd->device->id, - cmnd->device->lun, cmnd->serial_number); - + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, + "0749 SCSI Layer I/O Abort Request Status x%x ID %d " + "LUN %d snum %#lx\n", ret, cmnd->device->id, + cmnd->device->lun, cmnd->serial_number); return ret; } @@ -1158,12 +1134,11 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) loopcnt++; rdata = cmnd->device->hostdata; if (!rdata || - (loopcnt > ((phba->cfg_devloss_tmo * 2) + 1))) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d (%d):0721 LUN Reset rport " - "failure: cnt x%x rdata x%p\n", - phba->brd_no, vport->vpi, - loopcnt, rdata); + (loopcnt > ((vport->cfg_devloss_tmo * 2) + 1))){ + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0721 LUN Reset rport " + "failure: cnt x%x rdata x%p\n", + loopcnt, rdata); goto out; } pnode = rdata->pnode; @@ -1193,12 +1168,10 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) if (iocbqrsp == NULL) goto out_free_scsi_buf; - lpfc_printf_log(phba, KERN_INFO, LOG_FCP, - "%d (%d):0703 Issue target reset to TGT %d LUN %d " - "rpi x%x nlp_flag x%x\n", - phba->brd_no, vport->vpi, cmnd->device->id, - cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag); - + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "0703 Issue target reset to TGT %d LUN %d " + "rpi x%x nlp_flag x%x\n", cmnd->device->id, + cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag); iocb_status = lpfc_sli_issue_iocb_wait(phba, &phba->sli.ring[phba->sli.fcp_ring], iocbq, iocbqrsp, lpfc_cmd->timeout); @@ -1221,33 +1194,28 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) * Unfortunately, some targets do not abide by this forcing the driver * to double check. */ - cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], - cmnd->device->id, cmnd->device->lun, + cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id, cmnd->device->lun, LPFC_CTX_LUN); if (cnt) - lpfc_sli_abort_iocb(phba, - &phba->sli.ring[phba->sli.fcp_ring], + lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], cmnd->device->id, cmnd->device->lun, - 0, LPFC_CTX_LUN); + LPFC_CTX_LUN); loopcnt = 0; while(cnt) { schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); if (++loopcnt - > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT) + > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT) break; - cnt = lpfc_sli_sum_iocb(phba, - &phba->sli.ring[phba->sli.fcp_ring], - cmnd->device->id, cmnd->device->lun, - LPFC_CTX_LUN); + cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id, + cmnd->device->lun, LPFC_CTX_LUN); } if (cnt) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d (%d):0719 device reset I/O flush failure: " - "cnt x%x\n", - phba->brd_no, vport->vpi, cnt); + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0719 device reset I/O flush failure: " + "cnt x%x\n", cnt); ret = FAILED; } @@ -1255,12 +1223,11 @@ out_free_scsi_buf: if (iocb_status != IOCB_TIMEDOUT) { lpfc_release_scsi_buf(phba, lpfc_cmd); } - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d (%d):0713 SCSI layer issued device reset (%d, %d) " - "return x%x status x%x result x%x\n", - phba->brd_no, vport->vpi, cmnd->device->id, - cmnd->device->lun, ret, cmd_status, cmd_result); - + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0713 SCSI layer issued device reset (%d, %d) " + "return x%x status x%x result x%x\n", + cmnd->device->id, cmnd->device->lun, ret, + cmd_status, cmd_result); out: return ret; } @@ -1311,10 +1278,9 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) cmnd->device->lun, ndlp->rport->dd_data); if (ret != SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d (%d):0700 Bus Reset on target %d " - "failed\n", - phba->brd_no, vport->vpi, i); + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0700 Bus Reset on target %d failed\n", + i); err_count++; break; } @@ -1333,35 +1299,30 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) * the targets. Unfortunately, some targets do not abide by * this forcing the driver to double check. */ - cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], - 0, 0, LPFC_CTX_HOST); + cnt = lpfc_sli_sum_iocb(vport, 0, 0, LPFC_CTX_HOST); if (cnt) - lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], - 0, 0, 0, LPFC_CTX_HOST); + lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], + 0, 0, LPFC_CTX_HOST); loopcnt = 0; while(cnt) { schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); if (++loopcnt - > (2 * phba->cfg_devloss_tmo)/LPFC_RESET_WAIT) + > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT) break; - cnt = lpfc_sli_sum_iocb(phba, - &phba->sli.ring[phba->sli.fcp_ring], - 0, 0, LPFC_CTX_HOST); + cnt = lpfc_sli_sum_iocb(vport, 0, 0, LPFC_CTX_HOST); } if (cnt) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d (%d):0715 Bus Reset I/O flush failure: " - "cnt x%x left x%x\n", - phba->brd_no, vport->vpi, cnt, i); + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0715 Bus Reset I/O flush failure: " + "cnt x%x left x%x\n", cnt, i); ret = FAILED; } - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d (%d):0714 SCSI layer issued Bus Reset Data: x%x\n", - phba->brd_no, vport->vpi, ret); + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0714 SCSI layer issued Bus Reset Data: x%x\n", ret); out: return ret; } @@ -1390,36 +1351,32 @@ lpfc_slave_alloc(struct scsi_device *sdev) * extra. This list of scsi bufs exists for the lifetime of the driver. */ total = phba->total_scsi_bufs; - num_to_alloc = phba->cfg_lun_queue_depth + 2; + num_to_alloc = vport->cfg_lun_queue_depth + 2; /* Allow some exchanges to be available always to complete discovery */ if (total >= phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) { - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, - "%d (%d):0704 At limitation of %d " - "preallocated command buffers\n", - phba->brd_no, vport->vpi, total); + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, + "0704 At limitation of %d preallocated " + "command buffers\n", total); return 0; - /* Allow some exchanges to be available always to complete discovery */ } else if (total + num_to_alloc > phba->cfg_hba_queue_depth - LPFC_DISC_IOCB_BUFF_COUNT ) { - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, - "%d (%d):0705 Allocation request of %d " - "command buffers will exceed max of %d. " - "Reducing allocation request to %d.\n", - phba->brd_no, vport->vpi, num_to_alloc, - phba->cfg_hba_queue_depth, - (phba->cfg_hba_queue_depth - total)); + lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, + "0705 Allocation request of %d " + "command buffers will exceed max of %d. " + "Reducing allocation request to %d.\n", + num_to_alloc, phba->cfg_hba_queue_depth, + (phba->cfg_hba_queue_depth - total)); num_to_alloc = phba->cfg_hba_queue_depth - total; } for (i = 0; i < num_to_alloc; i++) { scsi_buf = lpfc_new_scsi_buf(vport); if (!scsi_buf) { - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d (%d):0706 Failed to allocate " - "command buffer\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0706 Failed to allocate " + "command buffer\n"); break; } @@ -1439,9 +1396,9 @@ lpfc_slave_configure(struct scsi_device *sdev) struct fc_rport *rport = starget_to_rport(sdev->sdev_target); if (sdev->tagged_supported) - scsi_activate_tcq(sdev, phba->cfg_lun_queue_depth); + scsi_activate_tcq(sdev, vport->cfg_lun_queue_depth); else - scsi_deactivate_tcq(sdev, phba->cfg_lun_queue_depth); + scsi_deactivate_tcq(sdev, vport->cfg_lun_queue_depth); /* * Initialize the fc transport attributes for the target @@ -1449,7 +1406,7 @@ lpfc_slave_configure(struct scsi_device *sdev) * target pointer is stored in the starget_data for the * driver's sysfs entry point functions. */ - rport->dev_loss_tmo = phba->cfg_devloss_tmo; + rport->dev_loss_tmo = vport->cfg_devloss_tmo; if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { lpfc_sli_poll_fcp_ring(phba); @@ -1487,3 +1444,23 @@ struct scsi_host_template lpfc_template = { .shost_attrs = lpfc_hba_attrs, .max_sectors = 0xFFFF, }; + +struct scsi_host_template lpfc_vport_template = { + .module = THIS_MODULE, + .name = LPFC_DRIVER_NAME, + .info = lpfc_info, + .queuecommand = lpfc_queuecommand, + .eh_abort_handler = lpfc_abort_handler, + .eh_device_reset_handler= lpfc_device_reset_handler, + .eh_bus_reset_handler = lpfc_bus_reset_handler, + .slave_alloc = lpfc_slave_alloc, + .slave_configure = lpfc_slave_configure, + .slave_destroy = lpfc_slave_destroy, + .scan_finished = lpfc_scan_finished, + .this_id = -1, + .sg_tablesize = LPFC_SG_SEG_CNT, + .cmd_per_lun = LPFC_CMD_PER_LUN, + .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = lpfc_vport_attrs, + .max_sectors = 0xFFFF, +}; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f4d5a6b00fd..ce5ff2bccba 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -49,9 +49,8 @@ lpfc_printf_log(phba, \ KERN_INFO, \ LOG_MBOX | LOG_SLI, \ - "%d (%d):0311 Mailbox command x%x cannot " \ + "(%d):0311 Mailbox command x%x cannot " \ "issue Data: x%x x%x x%x\n", \ - phba->brd_no, \ pmbox->vport ? pmbox->vport->vpi : 0, \ pmbox->mb.mbxCommand, \ phba->pport->port_state, \ @@ -231,13 +230,11 @@ lpfc_sli_ring_map(struct lpfc_hba *phba) rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0446 Adapter failed to init (%d), " + "0446 Adapter failed to init (%d), " "mbxCmd x%x CFG_RING, mbxStatus x%x, " "ring %d\n", - phba->brd_no, rc, - pmbox->mbxCommand, - pmbox->mbxStatus, - i); + rc, pmbox->mbxCommand, + pmbox->mbxStatus, i); phba->link_state = LPFC_HBA_ERROR; ret = -ENXIO; break; @@ -296,9 +293,9 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) if (unlikely(pring->local_getidx >= max_cmd_idx)) { lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0315 Ring %d issue: portCmdGet %d " + "0315 Ring %d issue: portCmdGet %d " "is bigger then cmd ring %d\n", - phba->brd_no, pring->ringno, + pring->ringno, pring->local_getidx, max_cmd_idx); phba->link_state = LPFC_HBA_ERROR; @@ -366,7 +363,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) if (psli->iocbq_lookup) memcpy(new_arr, old_arr, ((psli->last_iotag + 1) * - sizeof (struct lpfc_iocbq *))); + sizeof (struct lpfc_iocbq *))); psli->iocbq_lookup = new_arr; psli->iocbq_lookup_len = new_len; psli->last_iotag = iotag; @@ -380,8 +377,8 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) spin_unlock_irq(&phba->hbalock); lpfc_printf_log(phba, KERN_ERR,LOG_SLI, - "%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n", - phba->brd_no, psli->last_iotag); + "0318 Failed to allocate IOTAG.last IOTAG is %d\n", + psli->last_iotag); return 0; } @@ -395,6 +392,14 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, */ nextiocb->iocb.ulpIoTag = (nextiocb->iocb_cmpl) ? nextiocb->iotag : 0; + if (pring->ringno == LPFC_ELS_RING) { + lpfc_debugfs_slow_ring_trc(phba, + "IOCB cmd ring: wd4:x%08x wd6:x%08x wd7:x%08x", + *(((uint32_t *) &nextiocb->iocb) + 4), + *(((uint32_t *) &nextiocb->iocb) + 6), + *(((uint32_t *) &nextiocb->iocb) + 7)); + } + /* * Issue iocb command to adapter */ @@ -527,10 +532,9 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno) if (unlikely(hbqp->local_hbqGetIdx >= hbqp->entry_count)) { lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT, - "%d:1802 HBQ %d: local_hbqGetIdx " + "1802 HBQ %d: local_hbqGetIdx " "%u is > than hbqp->entry_count %u\n", - phba->brd_no, hbqno, - hbqp->local_hbqGetIdx, + hbqno, hbqp->local_hbqGetIdx, hbqp->entry_count); phba->link_state = LPFC_HBA_ERROR; @@ -541,7 +545,8 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno) return NULL; } - return (struct lpfc_hbq_entry *) phba->hbqslimp.virt + hbqp->hbqPutIdx; + return (struct lpfc_hbq_entry *) phba->hbqs[hbqno].hbq_virt + + hbqp->hbqPutIdx; } void @@ -549,18 +554,21 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) { struct lpfc_dmabuf *dmabuf, *next_dmabuf; struct hbq_dmabuf *hbq_buf; + int i, hbq_count; + hbq_count = lpfc_sli_hbq_count(); /* Return all memory used by all HBQs */ - list_for_each_entry_safe(dmabuf, next_dmabuf, - &phba->hbq_buffer_list, list) { - hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf); - list_del(&hbq_buf->dbuf.list); - lpfc_hbq_free(phba, hbq_buf->dbuf.virt, hbq_buf->dbuf.phys); - kfree(hbq_buf); + for (i = 0; i < hbq_count; ++i) { + list_for_each_entry_safe(dmabuf, next_dmabuf, + &phba->hbqs[i].hbq_buffer_list, list) { + hbq_buf = container_of(dmabuf, struct hbq_dmabuf, dbuf); + list_del(&hbq_buf->dbuf.list); + (phba->hbqs[i].hbq_free_buffer)(phba, hbq_buf); + } } } -static void +static struct lpfc_hbq_entry * lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, struct hbq_dmabuf *hbq_buf) { @@ -574,7 +582,7 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, hbqe->bde.addrHigh = le32_to_cpu(putPaddrHigh(physaddr)); hbqe->bde.addrLow = le32_to_cpu(putPaddrLow(physaddr)); - hbqe->bde.tus.f.bdeSize = FCELSSIZE; + hbqe->bde.tus.f.bdeSize = hbq_buf->size; hbqe->bde.tus.f.bdeFlags = 0; hbqe->bde.tus.w = le32_to_cpu(hbqe->bde.tus.w); hbqe->buffer_tag = le32_to_cpu(hbq_buf->tag); @@ -583,8 +591,9 @@ lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno, writel(hbqp->hbqPutIdx, phba->hbq_put + hbqno); /* flush */ readl(phba->hbq_put + hbqno); - list_add_tail(&hbq_buf->dbuf.list, &phba->hbq_buffer_list); + list_add_tail(&hbq_buf->dbuf.list, &hbqp->hbq_buffer_list); } + return hbqe; } static struct lpfc_hbq_init lpfc_els_hbq = { @@ -592,22 +601,38 @@ static struct lpfc_hbq_init lpfc_els_hbq = { .entry_count = 200, .mask_count = 0, .profile = 0, - .ring_mask = 1 << LPFC_ELS_RING, + .ring_mask = (1 << LPFC_ELS_RING), .buffer_count = 0, .init_count = 20, .add_count = 5, }; -static struct lpfc_hbq_init *lpfc_hbq_defs[] = { +static struct lpfc_hbq_init lpfc_extra_hbq = { + .rn = 1, + .entry_count = 200, + .mask_count = 0, + .profile = 0, + .ring_mask = (1 << LPFC_EXTRA_RING), + .buffer_count = 0, + .init_count = 0, + .add_count = 5, +}; + +struct lpfc_hbq_init *lpfc_hbq_defs[] = { &lpfc_els_hbq, + &lpfc_extra_hbq, }; -int +static int lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) { uint32_t i, start, end; struct hbq_dmabuf *hbq_buffer; + if (!phba->hbqs[hbqno].hbq_alloc_buffer) { + return 0; + } + start = lpfc_hbq_defs[hbqno]->buffer_count; end = count + lpfc_hbq_defs[hbqno]->buffer_count; if (end > lpfc_hbq_defs[hbqno]->entry_count) { @@ -616,17 +641,14 @@ lpfc_sli_hbqbuf_fill_hbqs(struct lpfc_hba *phba, uint32_t hbqno, uint32_t count) /* Populate HBQ entries */ for (i = start; i < end; i++) { - hbq_buffer = kmalloc(sizeof(struct hbq_dmabuf), - GFP_KERNEL); + hbq_buffer = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba); if (!hbq_buffer) return 1; - hbq_buffer->dbuf.virt = lpfc_hbq_alloc(phba, MEM_PRI, - &hbq_buffer->dbuf.phys); - if (hbq_buffer->dbuf.virt == NULL) - return 1; hbq_buffer->tag = (i | (hbqno << 16)); - lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer); - lpfc_hbq_defs[hbqno]->buffer_count++; + if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) + lpfc_hbq_defs[hbqno]->buffer_count++; + else + (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer); } return 0; } @@ -650,28 +672,34 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) { struct lpfc_dmabuf *d_buf; struct hbq_dmabuf *hbq_buf; + uint32_t hbqno; + + hbqno = tag >> 16; + if (hbqno > LPFC_MAX_HBQS) + return NULL; - list_for_each_entry(d_buf, &phba->hbq_buffer_list, list) { + list_for_each_entry(d_buf, &phba->hbqs[hbqno].hbq_buffer_list, list) { hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf); - if ((hbq_buf->tag & 0xffff) == tag) { + if (hbq_buf->tag == tag) { return hbq_buf; } } lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT, - "%d:1803 Bad hbq tag. Data: x%x x%x\n", - phba->brd_no, tag, - lpfc_hbq_defs[tag >> 16]->buffer_count); + "1803 Bad hbq tag. Data: x%x x%x\n", + tag, lpfc_hbq_defs[tag >> 16]->buffer_count); return NULL; } void -lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *sp) +lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer) { uint32_t hbqno; - if (sp) { - hbqno = sp->tag >> 16; - lpfc_sli_hbq_to_firmware(phba, hbqno, sp); + if (hbq_buffer) { + hbqno = hbq_buffer->tag >> 16; + if (!lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer)) { + (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer); + } } } @@ -837,12 +865,10 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) */ if (lpfc_sli_chk_mbx_command(pmbox->mbxCommand) == MBX_SHUTDOWN) { - /* Unknow mailbox command compl */ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "%d (%d):0323 Unknown Mailbox command " + "(%d):0323 Unknown Mailbox command " "%x Cmpl\n", - phba->brd_no, pmb->vport ? pmb->vport->vpi : 0, pmbox->mbxCommand); phba->link_state = LPFC_HBA_ERROR; @@ -857,10 +883,9 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) /* Mbox cmd cmpl error - RETRYing */ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "%d (%d):0305 Mbox cmd cmpl " + "(%d):0305 Mbox cmd cmpl " "error - RETRYing Data: x%x " "x%x x%x x%x\n", - phba->brd_no, pmb->vport ? pmb->vport->vpi :0, pmbox->mbxCommand, pmbox->mbxStatus, @@ -879,9 +904,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) /* Mailbox cmd <cmd> Cmpl <cmpl> */ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "%d (%d):0307 Mailbox cmd x%x Cmpl x%p " + "(%d):0307 Mailbox cmd x%x Cmpl x%p " "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n", - phba->brd_no, pmb->vport ? pmb->vport->vpi : 0, pmbox->mbxCommand, pmb->mbox_cmpl, @@ -905,21 +929,26 @@ static struct lpfc_dmabuf * lpfc_sli_replace_hbqbuff(struct lpfc_hba *phba, uint32_t tag) { struct hbq_dmabuf *hbq_entry, *new_hbq_entry; + uint32_t hbqno; + void *virt; /* virtual address ptr */ + dma_addr_t phys; /* mapped address */ hbq_entry = lpfc_sli_hbqbuf_find(phba, tag); if (hbq_entry == NULL) return NULL; list_del(&hbq_entry->dbuf.list); - new_hbq_entry = kmalloc(sizeof(struct hbq_dmabuf), GFP_ATOMIC); + + hbqno = tag >> 16; + new_hbq_entry = (phba->hbqs[hbqno].hbq_alloc_buffer)(phba); if (new_hbq_entry == NULL) return &hbq_entry->dbuf; - new_hbq_entry->dbuf = hbq_entry->dbuf; new_hbq_entry->tag = -1; - hbq_entry->dbuf.virt = lpfc_hbq_alloc(phba, 0, &hbq_entry->dbuf.phys); - if (hbq_entry->dbuf.virt == NULL) { - kfree(new_hbq_entry); - return &hbq_entry->dbuf; - } + phys = new_hbq_entry->dbuf.phys; + virt = new_hbq_entry->dbuf.virt; + new_hbq_entry->dbuf.phys = hbq_entry->dbuf.phys; + new_hbq_entry->dbuf.virt = hbq_entry->dbuf.virt; + hbq_entry->dbuf.phys = phys; + hbq_entry->dbuf.virt = virt; lpfc_sli_free_hbq(phba, hbq_entry); return &new_hbq_entry->dbuf; } @@ -965,7 +994,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, irsp->un.ulpWord[3]); if (irsp->ulpBdeCount == 2) saveq->context3 = lpfc_sli_replace_hbqbuff(phba, - irsp->un.ulpWord[15]); + irsp->unsli3.sli3Words[7]); } /* unSolicited Responses */ @@ -996,12 +1025,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* Ring <ringno> handler: unexpected Rctl <Rctl> Type <Type> received */ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "%d:0313 Ring %d handler: unexpected Rctl x%x " + "0313 Ring %d handler: unexpected Rctl x%x " "Type x%x received\n", - phba->brd_no, - pring->ringno, - Rctl, - Type); + pring->ringno, Rctl, Type); } return 1; } @@ -1024,10 +1050,9 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, } lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0317 iotag x%x is out off " + "0317 iotag x%x is out off " "range: max iotag x%x wd0 x%x\n", - phba->brd_no, iotag, - phba->sli.last_iotag, + iotag, phba->sli.last_iotag, *(((uint32_t *) &prspiocb->iocb) + 7)); return NULL; } @@ -1075,18 +1100,16 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, * Ring <ringno> handler: unexpected completion IoTag * <IoTag> */ - lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "%d (%d):0322 Ring %d handler: " - "unexpected completion IoTag x%x " - "Data: x%x x%x x%x x%x\n", - phba->brd_no, - cmdiocbp->vport->vpi, - pring->ringno, - saveq->iocb.ulpIoTag, - saveq->iocb.ulpStatus, - saveq->iocb.un.ulpWord[4], - saveq->iocb.ulpCommand, - saveq->iocb.ulpContext); + lpfc_printf_vlog(cmdiocbp->vport, KERN_WARNING, LOG_SLI, + "0322 Ring %d handler: " + "unexpected completion IoTag x%x " + "Data: x%x x%x x%x x%x\n", + pring->ringno, + saveq->iocb.ulpIoTag, + saveq->iocb.ulpStatus, + saveq->iocb.un.ulpWord[4], + saveq->iocb.ulpCommand, + saveq->iocb.ulpContext); } } @@ -1104,10 +1127,9 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) * rsp ring <portRspMax> */ lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0312 Ring %d handler: portRspPut %d " + "0312 Ring %d handler: portRspPut %d " "is bigger then rsp ring %d\n", - phba->brd_no, pring->ringno, - le32_to_cpu(pgp->rspPutInx), + pring->ringno, le32_to_cpu(pgp->rspPutInx), pring->numRiocb); phba->link_state = LPFC_HBA_ERROR; @@ -1177,9 +1199,9 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba) if (unlikely(irsp->ulpStatus)) { /* Rsp ring <ringno> error: IOCB */ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "%d:0326 Rsp Ring %d error: IOCB Data: " + "0326 Rsp Ring %d error: IOCB Data: " "x%x x%x x%x x%x x%x x%x x%x x%x\n", - phba->brd_no, pring->ringno, + pring->ringno, irsp->un.ulpWord[0], irsp->un.ulpWord[1], irsp->un.ulpWord[2], @@ -1199,9 +1221,9 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba) */ if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0314 IOCB cmd 0x%x" - " processed. Skipping" - " completion", phba->brd_no, + "0314 IOCB cmd 0x%x " + "processed. Skipping " + "completion", irsp->ulpCommand); break; } @@ -1226,10 +1248,9 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba) } else { /* Unknown IOCB command */ lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0321 Unknown IOCB command " + "0321 Unknown IOCB command " "Data: x%x, x%x x%x x%x x%x\n", - phba->brd_no, type, - irsp->ulpCommand, + type, irsp->ulpCommand, irsp->ulpStatus, irsp->ulpIoTag, irsp->ulpContext); @@ -1353,9 +1374,9 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, /* Rsp ring <ringno> error: IOCB */ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "%d:0336 Rsp Ring %d error: IOCB Data: " + "0336 Rsp Ring %d error: IOCB Data: " "x%x x%x x%x x%x x%x x%x x%x x%x\n", - phba->brd_no, pring->ringno, + pring->ringno, irsp->un.ulpWord[0], irsp->un.ulpWord[1], irsp->un.ulpWord[2], @@ -1375,10 +1396,9 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, */ if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0333 IOCB cmd 0x%x" + "0333 IOCB cmd 0x%x" " processed. Skipping" " completion\n", - phba->brd_no, irsp->ulpCommand); break; } @@ -1415,10 +1435,9 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, } else { /* Unknown IOCB command */ lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0334 Unknown IOCB command " + "0334 Unknown IOCB command " "Data: x%x, x%x x%x x%x x%x\n", - phba->brd_no, type, - irsp->ulpCommand, + type, irsp->ulpCommand, irsp->ulpStatus, irsp->ulpIoTag, irsp->ulpContext); @@ -1496,10 +1515,9 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, * rsp ring <portRspMax> */ lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0303 Ring %d handler: portRspPut %d " + "0303 Ring %d handler: portRspPut %d " "is bigger then rsp ring %d\n", - phba->brd_no, pring->ringno, portRspPut, - portRspMax); + pring->ringno, portRspPut, portRspMax); phba->link_state = LPFC_HBA_ERROR; spin_unlock_irqrestore(&phba->hbalock, iflag); @@ -1542,6 +1560,14 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, if (++pring->rspidx >= portRspMax) pring->rspidx = 0; + if (pring->ringno == LPFC_ELS_RING) { + lpfc_debugfs_slow_ring_trc(phba, + "IOCB rsp ring: wd4:x%08x wd6:x%08x wd7:x%08x", + *(((uint32_t *) irsp) + 4), + *(((uint32_t *) irsp) + 6), + *(((uint32_t *) irsp) + 7)); + } + writel(pring->rspidx, &phba->host_gp[pring->ringno].rspGetInx); if (list_empty(&(pring->iocb_continueq))) { @@ -1580,13 +1606,12 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, if (irsp->ulpStatus) { /* Rsp ring <ringno> error: IOCB */ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "%d:0328 Rsp Ring %d error: " + "0328 Rsp Ring %d error: " "IOCB Data: " "x%x x%x x%x x%x " "x%x x%x x%x x%x " "x%x x%x x%x x%x " "x%x x%x x%x x%x\n", - phba->brd_no, pring->ringno, irsp->un.ulpWord[0], irsp->un.ulpWord[1], @@ -1661,10 +1686,9 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, } else { /* Unknown IOCB command */ lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0335 Unknown IOCB " + "0335 Unknown IOCB " "command Data: x%x " "x%x x%x x%x\n", - phba->brd_no, irsp->ulpCommand, irsp->ulpStatus, irsp->ulpIoTag, @@ -1892,8 +1916,8 @@ lpfc_sli_brdkill(struct lpfc_hba *phba) /* Kill HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0329 Kill HBA Data: x%x x%x\n", - phba->brd_no, phba->pport->port_state, psli->sli_flag); + "0329 Kill HBA Data: x%x x%x\n", + phba->pport->port_state, psli->sli_flag); if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) == 0) @@ -1966,7 +1990,7 @@ lpfc_sli_brdreset(struct lpfc_hba *phba) /* Reset HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no, + "0325 Reset HBA Data: x%x x%x\n", phba->pport->port_state, psli->sli_flag); /* perform board reset */ @@ -2021,7 +2045,7 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba) /* Restart HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0337 Restart HBA Data: x%x x%x\n", phba->brd_no, + "0337 Restart HBA Data: x%x x%x\n", phba->pport->port_state, psli->sli_flag); word0 = 0; @@ -2086,9 +2110,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) /* Adapter failed to init, timeout, status reg <status> */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0436 Adapter failed to init, " - "timeout, status reg x%x\n", - phba->brd_no, status); + "0436 Adapter failed to init, " + "timeout, status reg x%x\n", status); phba->link_state = LPFC_HBA_ERROR; return -ETIMEDOUT; } @@ -2099,10 +2122,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) /* Adapter failed to init, chipset, status reg <status> */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0437 Adapter failed to init, " - "chipset, status reg x%x\n", - phba->brd_no, - status); + "0437 Adapter failed to init, " + "chipset, status reg x%x\n", status); phba->link_state = LPFC_HBA_ERROR; return -EIO; } @@ -2129,10 +2150,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) /* ERROR: During chipset initialization */ /* Adapter failed to init, chipset, status reg <status> */ lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0438 Adapter failed to init, chipset, " - "status reg x%x\n", - phba->brd_no, - status); + "0438 Adapter failed to init, chipset, " + "status reg x%x\n", status); phba->link_state = LPFC_HBA_ERROR; return -EIO; } @@ -2147,7 +2166,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) return 0; } -static int +int lpfc_sli_hbq_count(void) { return ARRAY_SIZE(lpfc_hbq_defs); @@ -2200,8 +2219,8 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba) phba->hbqs[hbqno].local_hbqGetIdx = 0; phba->hbqs[hbqno].entry_count = lpfc_hbq_defs[hbqno]->entry_count; - lpfc_config_hbq(phba, lpfc_hbq_defs[hbqno], hbq_entry_index, - pmb); + lpfc_config_hbq(phba, hbqno, lpfc_hbq_defs[hbqno], + hbq_entry_index, pmb); hbq_entry_index += phba->hbqs[hbqno].entry_count; if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) { @@ -2210,9 +2229,9 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba) lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT, - "%d:1805 Adapter failed to init. " + "1805 Adapter failed to init. " "Data: x%x x%x x%x\n", - phba->brd_no, pmbox->mbxCommand, + pmbox->mbxCommand, pmbox->mbxStatus, hbqno); phba->link_state = LPFC_HBA_ERROR; @@ -2279,10 +2298,9 @@ lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode) rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0442 Adapter failed to init, mbxCmd x%x " + "0442 Adapter failed to init, mbxCmd x%x " "CONFIG_PORT, mbxStatus x%x Data: x%x\n", - phba->brd_no, pmb->mb.mbxCommand, - pmb->mb.mbxStatus, 0); + pmb->mb.mbxCommand, pmb->mb.mbxStatus, 0); spin_lock_irq(&phba->hbalock); phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE; spin_unlock_irq(&phba->hbalock); @@ -2321,11 +2339,11 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) switch (lpfc_sli_mode) { case 2: - if (phba->cfg_npiv_enable) { + if (phba->cfg_enable_npiv) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, - "%d:1824 NPIV enabled: Override lpfc_sli_mode " + "1824 NPIV enabled: Override lpfc_sli_mode " "parameter (%d) to auto (0).\n", - phba->brd_no, lpfc_sli_mode); + lpfc_sli_mode); break; } mode = 2; @@ -2335,9 +2353,8 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) break; default: lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, - "%d:1819 Unrecognized lpfc_sli_mode " - "parameter: %d.\n", - phba->brd_no, lpfc_sli_mode); + "1819 Unrecognized lpfc_sli_mode " + "parameter: %d.\n", lpfc_sli_mode); break; } @@ -2345,9 +2362,8 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) rc = lpfc_do_config_port(phba, mode); if (rc && lpfc_sli_mode == 3) lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, - "%d:1820 Unable to select SLI-3. " - "Not supported by adapter.\n", - phba->brd_no); + "1820 Unable to select SLI-3. " + "Not supported by adapter.\n"); if (rc && mode != 2) rc = lpfc_do_config_port(phba, 2); if (rc) @@ -2366,8 +2382,8 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) } lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0444 Firmware in SLI %x mode. Max_vpi %d\n", - phba->brd_no, phba->sli_rev, phba->max_vpi); + "0444 Firmware in SLI %x mode. Max_vpi %d\n", + phba->sli_rev, phba->max_vpi); rc = lpfc_sli_ring_map(phba); if (rc) @@ -2392,8 +2408,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) lpfc_sli_hba_setup_error: phba->link_state = LPFC_HBA_ERROR; lpfc_printf_log(phba, KERN_INFO, LOG_INIT, - "%d:0445 Firmware initialization failed\n", - phba->brd_no); + "0445 Firmware initialization failed\n"); return rc; } @@ -2445,9 +2460,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) /* Mbox cmd <mbxCommand> timeout */ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "%d:0310 Mailbox command x%x timeout Data: x%x x%x " - "x%p\n", - phba->brd_no, + "0310 Mailbox command x%x timeout Data: x%x x%x x%p\n", mb->mbxCommand, phba->pport->port_state, phba->sli.sli_flag, @@ -2470,8 +2483,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) lpfc_sli_abort_iocb_ring(phba, pring); lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, - "%d:0316 Resetting board due to mailbox timeout\n", - phba->brd_no); + "0316 Resetting board due to mailbox timeout\n"); /* * lpfc_offline calls lpfc_sli_hba_down which will clean up * on oustanding mailbox commands. @@ -2502,8 +2514,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) if(!pmbox->vport) { lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_VPORT, - "%d:1806 Mbox x%x failed. No vport\n", - phba->brd_no, + "1806 Mbox x%x failed. No vport\n", pmbox->mb.mbxCommand); dump_stack(); return MBXERR_ERROR; @@ -2580,9 +2591,8 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) /* Mbox cmd issue - BUSY */ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "%d (%d):0308 Mbox cmd issue - BUSY Data: " + "(%d):0308 Mbox cmd issue - BUSY Data: " "x%x x%x x%x x%x\n", - phba->brd_no, pmbox->vport ? pmbox->vport->vpi : 0xffffff, mb->mbxCommand, phba->pport->port_state, psli->sli_flag, flag); @@ -2644,9 +2654,9 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) /* Mailbox cmd <cmd> issue */ lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, - "%d (%d):0309 Mailbox cmd x%x issue Data: x%x x%x " + "(%d):0309 Mailbox cmd x%x issue Data: x%x x%x " "x%x\n", - phba->brd_no, pmbox->vport ? pmbox->vport->vpi : 0, + pmbox->vport ? pmbox->vport->vpi : 0, mb->mbxCommand, phba->pport->port_state, psli->sli_flag, flag); @@ -2848,8 +2858,7 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) { lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT, - "%d:1807 IOCB x%x failed. No vport\n", - phba->brd_no, + "1807 IOCB x%x failed. No vport\n", piocb->iocb.ulpCommand); dump_stack(); return IOCB_ERROR; @@ -3080,11 +3089,10 @@ lpfc_sli_setup(struct lpfc_hba *phba) } if (totiocbsize > MAX_SLIM_IOCB_SIZE) { /* Too many cmd / rsp ring entries in SLI2 SLIM */ - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0462 Too many cmd / rsp ring entries in " - "SLI2 SLIM Data: x%x x%lx\n", - phba->brd_no, totiocbsize, - (unsigned long) MAX_SLIM_IOCB_SIZE); + printk(KERN_ERR "%d:0462 Too many cmd / rsp ring entries in " + "SLI2 SLIM Data: x%x x%lx\n", + phba->brd_no, totiocbsize, + (unsigned long) MAX_SLIM_IOCB_SIZE); } if (phba->cfg_multi_ring_support == 2) lpfc_extra_ring_setup(phba); @@ -3305,9 +3313,9 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, spin_unlock_irq(&phba->hbalock); lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "%d:0410 Cannot find virtual addr for mapped buf on " + "0410 Cannot find virtual addr for mapped buf on " "ring %d Data x%llx x%p x%p x%x\n", - phba->brd_no, pring->ringno, (unsigned long long)phys, + pring->ringno, (unsigned long long)phys, slp->next, slp->prev, pring->postbufq_cnt); return NULL; } @@ -3332,12 +3340,11 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, abort_iocb = phba->sli.iocbq_lookup[abort_iotag]; lpfc_printf_log(phba, KERN_INFO, LOG_ELS | LOG_SLI, - "%d:0327 Cannot abort els iocb %p " + "0327 Cannot abort els iocb %p " "with tag %x context %x, abort status %x, " "abort code %x\n", - phba->brd_no, abort_iocb, abort_iotag, - abort_context, irsp->ulpStatus, - irsp->un.ulpWord[4]); + abort_iocb, abort_iotag, abort_context, + irsp->ulpStatus, irsp->un.ulpWord[4]); /* * make sure we have the right iocbq before taking it @@ -3371,9 +3378,9 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* ELS cmd tag <ulpIoTag> completes */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d (X):0133 Ignoring ELS cmd tag x%x completion Data: " + "0133 Ignoring ELS cmd tag x%x completion Data: " "x%x x%x x%x\n", - phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus, + irsp->ulpIoTag, irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout); if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) lpfc_ct_free_iocb(phba, cmdiocb); @@ -3439,12 +3446,11 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; - lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d (%d):0339 Abort xri x%x, original iotag x%x, " - "abort cmd iotag x%x\n", - phba->brd_no, vport->vpi, - iabt->un.acxri.abortContextTag, - iabt->un.acxri.abortIoTag, abtsiocbp->iotag); + lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, + "0339 Abort xri x%x, original iotag x%x, " + "abort cmd iotag x%x\n", + iabt->un.acxri.abortContextTag, + iabt->un.acxri.abortIoTag, abtsiocbp->iotag); retval = __lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0); abort_iotag_exit: @@ -3457,8 +3463,8 @@ abort_iotag_exit: } static int -lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, - uint64_t lun_id, uint32_t ctx, +lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, + uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) { struct lpfc_scsi_buf *lpfc_cmd; @@ -3468,6 +3474,9 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, if (!(iocbq->iocb_flag & LPFC_IO_FCP)) return rc; + if (iocbq->vport != vport) + return rc; + lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); cmnd = lpfc_cmd->pCmd; @@ -3484,10 +3493,6 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, if (cmnd->device->id == tgt_id) rc = 0; break; - case LPFC_CTX_CTX: - if (iocbq->iocb.ulpContext == ctx) - rc = 0; - break; case LPFC_CTX_HOST: rc = 0; break; @@ -3501,17 +3506,18 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, uint16_t tgt_id, } int -lpfc_sli_sum_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, - uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd ctx_cmd) +lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, + lpfc_ctx_cmd ctx_cmd) { + struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *iocbq; int sum, i; for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) { iocbq = phba->sli.iocbq_lookup[i]; - if (lpfc_sli_validate_fcp_iocb (iocbq, tgt_id, lun_id, - 0, ctx_cmd) == 0) + if (lpfc_sli_validate_fcp_iocb (iocbq, vport, tgt_id, lun_id, + ctx_cmd) == 0) sum++; } @@ -3527,10 +3533,10 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } int -lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, - uint16_t tgt_id, uint64_t lun_id, uint32_t ctx, - lpfc_ctx_cmd abort_cmd) +lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, + uint16_t tgt_id, uint64_t lun_id, lpfc_ctx_cmd abort_cmd) { + struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *iocbq; struct lpfc_iocbq *abtsiocb; IOCB_t *cmd = NULL; @@ -3540,7 +3546,7 @@ lpfc_sli_abort_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, for (i = 1; i <= phba->sli.last_iotag; i++) { iocbq = phba->sli.iocbq_lookup[i]; - if (lpfc_sli_validate_fcp_iocb(iocbq, tgt_id, lun_id, 0, + if (lpfc_sli_validate_fcp_iocb(iocbq, vport, tgt_id, lun_id, abort_cmd) != 0) continue; @@ -3647,25 +3653,23 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, if (piocb->iocb_flag & LPFC_IO_WAKE) { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0331 IOCB wake signaled\n", - phba->brd_no); + "0331 IOCB wake signaled\n"); } else if (timeleft == 0) { lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0338 IOCB wait timeout error - no " - "wake response Data x%x\n", - phba->brd_no, timeout); + "0338 IOCB wait timeout error - no " + "wake response Data x%x\n", timeout); retval = IOCB_TIMEDOUT; } else { lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0330 IOCB wake NOT set, " - "Data x%x x%lx\n", phba->brd_no, + "0330 IOCB wake NOT set, " + "Data x%x x%lx\n", timeout, (timeleft / jiffies)); retval = IOCB_TIMEDOUT; } } else { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0332 IOCB wait issue failed, Data x%x\n", - phba->brd_no, retval); + ":0332 IOCB wait issue failed, Data x%x\n", + retval); retval = IOCB_ERROR; } @@ -3850,12 +3854,33 @@ lpfc_intr_handler(int irq, void *dev_id) if (status & HA_RXMASK) { spin_lock(&phba->hbalock); control = readl(phba->HCregaddr); + + lpfc_debugfs_slow_ring_trc(phba, + "ISR slow ring: ctl:x%x stat:x%x isrcnt:x%x", + control, status, + (uint32_t)phba->sli.slistat.sli_intr); + if (control & (HC_R0INT_ENA << LPFC_ELS_RING)) { + lpfc_debugfs_slow_ring_trc(phba, + "ISR Disable ring:" + "pwork:x%x hawork:x%x wait:x%x", + phba->work_ha, work_ha_copy, + (uint32_t)((unsigned long) + phba->work_wait)); + control &= ~(HC_R0INT_ENA << LPFC_ELS_RING); writel(control, phba->HCregaddr); readl(phba->HCregaddr); /* flush */ } + else { + lpfc_debugfs_slow_ring_trc(phba, + "ISR slow ring: pwork:" + "x%x hawork:x%x wait:x%x", + phba->work_ha, work_ha_copy, + (uint32_t)((unsigned long) + phba->work_wait)); + } spin_unlock(&phba->hbalock); } } @@ -3895,12 +3920,10 @@ lpfc_intr_handler(int irq, void *dev_id) */ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX | LOG_SLI, - "%d (%d):0304 Stray Mailbox " + "(%d):0304 Stray Mailbox " "Interrupt mbxCommand x%x " "mbxStatus x%x\n", - phba->brd_no, - (vport - ? vport->vpi : 0), + (vport ? vport->vpi : 0), pmbox->mbxCommand, pmbox->mbxStatus); } diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 76058505795..51b2b6b949b 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -26,7 +26,6 @@ struct lpfc_vport; typedef enum _lpfc_ctx_cmd { LPFC_CTX_LUN, LPFC_CTX_TGT, - LPFC_CTX_CTX, LPFC_CTX_HOST } lpfc_ctx_cmd; @@ -54,9 +53,10 @@ struct lpfc_iocbq { void *context2; /* caller context information */ void *context3; /* caller context information */ union { - wait_queue_head_t *wait_queue; - struct lpfc_iocbq *rsp_iocb; - struct lpfcMboxq *mbox; + wait_queue_head_t *wait_queue; + struct lpfc_iocbq *rsp_iocb; + struct lpfcMboxq *mbox; + struct lpfc_nodelist *ndlp; } context_un; void (*fabric_iocb_cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, @@ -143,7 +143,7 @@ struct lpfc_sli_ring { uint16_t numCiocb; /* number of command iocb's per ring */ uint16_t numRiocb; /* number of rsp iocb's per ring */ uint16_t sizeCiocb; /* Size of command iocb's in this ring */ - uint16_t sizeRiocb; /* Size of response iocb's in this ring */ + uint16_t sizeRiocb; /* Size of response iocb's in this ring */ uint32_t fast_iotag; /* max fastlookup based iotag */ uint32_t iotag_ctr; /* keeps track of the next iotag to use */ diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index a5bc79eef05..0081f49286b 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,12 +18,10 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.2.1" +#define LPFC_DRIVER_VERSION "8.2.2" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ LPFC_DRIVER_VERSION #define LPFC_COPYRIGHT "Copyright(c) 2004-2007 Emulex. All rights reserved." - -#define DFC_API_VERSION "0.0.0" diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 85797dbf547..dcb415e717c 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -125,11 +125,10 @@ lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport) pmb->vport = vport; rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2); if (rc != MBX_SUCCESS) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, - "%d (%d):1818 VPort failed init, mbxCmd x%x " - "READ_SPARM mbxStatus x%x, rc = x%x\n", - phba->brd_no, vport->vpi, - mb->mbxCommand, mb->mbxStatus, rc); + lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT, + "1818 VPort failed init, mbxCmd x%x " + "READ_SPARM mbxStatus x%x, rc = x%x\n", + mb->mbxCommand, mb->mbxStatus, rc); lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); if (rc != MBX_TIMEOUT) @@ -162,9 +161,9 @@ lpfc_valid_wwn_format(struct lpfc_hba *phba, struct lpfc_name *wwn, return 1; lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, - "%d:1822 Invalid %s: %02x:%02x:%02x:%02x:" + "1822 Invalid %s: %02x:%02x:%02x:%02x:" "%02x:%02x:%02x:%02x\n", - phba->brd_no, name_type, + name_type, wwn->u.wwn[0], wwn->u.wwn[1], wwn->u.wwn[2], wwn->u.wwn[3], wwn->u.wwn[4], wwn->u.wwn[5], @@ -176,16 +175,21 @@ static int lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport) { struct lpfc_vport *vport; + unsigned long flags; + spin_lock_irqsave(&phba->hbalock, flags); list_for_each_entry(vport, &phba->port_list, listentry) { if (vport == new_vport) continue; /* If they match, return not unique */ if (memcmp(&vport->fc_sparam.portName, - &new_vport->fc_sparam.portName, - sizeof(struct lpfc_name)) == 0) + &new_vport->fc_sparam.portName, + sizeof(struct lpfc_name)) == 0) { + spin_unlock_irqrestore(&phba->hbalock, flags); return 0; + } } + spin_unlock_irqrestore(&phba->hbalock, flags); return 1; } @@ -193,8 +197,8 @@ int lpfc_vport_create(struct fc_vport *fc_vport, bool disable) { struct lpfc_nodelist *ndlp; - struct lpfc_vport *pport = - (struct lpfc_vport *) fc_vport->shost->hostdata; + struct Scsi_Host *shost = fc_vport->shost; + struct lpfc_vport *pport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = pport->phba; struct lpfc_vport *vport = NULL; int instance; @@ -204,9 +208,9 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) if ((phba->sli_rev < 3) || !(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) { lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, - "%d:1808 Create VPORT failed: " + "1808 Create VPORT failed: " "NPIV is not enabled: SLImode:%d\n", - phba->brd_no, phba->sli_rev); + phba->sli_rev); rc = VPORT_INVAL; goto error_out; } @@ -214,9 +218,9 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) vpi = lpfc_alloc_vpi(phba); if (vpi == 0) { lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, - "%d:1809 Create VPORT failed: " + "1809 Create VPORT failed: " "Max VPORTs (%d) exceeded\n", - phba->brd_no, phba->max_vpi); + phba->max_vpi); rc = VPORT_NORESOURCES; goto error_out; } @@ -225,18 +229,17 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) /* Assign an unused board number */ if ((instance = lpfc_get_instance()) < 0) { lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, - "%d:1810 Create VPORT failed: Cannot get " - "instance number\n", phba->brd_no); + "1810 Create VPORT failed: Cannot get " + "instance number\n"); lpfc_free_vpi(phba, vpi); rc = VPORT_NORESOURCES; goto error_out; } - vport = lpfc_create_port(phba, instance, fc_vport); + vport = lpfc_create_port(phba, instance, &fc_vport->dev); if (!vport) { lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, - "%d:1811 Create VPORT failed: vpi x%x\n", - phba->brd_no, vpi); + "1811 Create VPORT failed: vpi x%x\n", vpi); lpfc_free_vpi(phba, vpi); rc = VPORT_NORESOURCES; goto error_out; @@ -246,10 +249,9 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) lpfc_debugfs_initialize(vport); if (lpfc_vport_sparm(phba, vport)) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, - "%d:1813 Create VPORT failed: vpi:%d " - "Cannot get sparam\n", - phba->brd_no, vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + "1813 Create VPORT failed. " + "Cannot get sparam\n"); lpfc_free_vpi(phba, vpi); destroy_port(vport); rc = VPORT_NORESOURCES; @@ -269,10 +271,9 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) if (!lpfc_valid_wwn_format(phba, &vport->fc_sparam.nodeName, "WWNN") || !lpfc_valid_wwn_format(phba, &vport->fc_sparam.portName, "WWPN")) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, - "%d:1821 Create VPORT failed: vpi:%d " - "Invalid WWN format\n", - phba->brd_no, vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + "1821 Create VPORT failed. " + "Invalid WWN format\n"); lpfc_free_vpi(phba, vpi); destroy_port(vport); rc = VPORT_INVAL; @@ -280,10 +281,9 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) } if (!lpfc_unique_wwpn(phba, vport)) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, - "%d:1823 Create VPORT failed: vpi:%d " - "Duplicate WWN on HBA\n", - phba->brd_no, vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + "1823 Create VPORT failed. " + "Duplicate WWN on HBA\n"); lpfc_free_vpi(phba, vpi); destroy_port(vport); rc = VPORT_INVAL; @@ -315,10 +315,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) lpfc_initial_fdisc(vport); } else { lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0262 No NPIV Fabric " - "support\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0262 No NPIV Fabric support\n"); } } else { lpfc_vport_set_state(vport, FC_VPORT_FAILED); @@ -326,12 +324,14 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) rc = VPORT_OK; out: + lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + "1825 Vport Created.\n"); lpfc_host_attrib_init(lpfc_shost_from_vport(vport)); error_out: return rc; } -int +static int disable_vport(struct fc_vport *fc_vport) { struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; @@ -371,10 +371,12 @@ disable_vport(struct fc_vport *fc_vport) lpfc_mbx_unreg_vpi(vport); lpfc_vport_set_state(vport, FC_VPORT_DISABLED); + lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + "1826 Vport Disabled.\n"); return VPORT_OK; } -int +static int enable_vport(struct fc_vport *fc_vport) { struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; @@ -400,15 +402,14 @@ enable_vport(struct fc_vport *fc_vport) lpfc_initial_fdisc(vport); } else { lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP); - lpfc_printf_log(phba, KERN_ERR, LOG_ELS, - "%d (%d):0264 No NPIV Fabric " - "support\n", - phba->brd_no, vport->vpi); + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "0264 No NPIV Fabric support\n"); } } else { lpfc_vport_set_state(vport, FC_VPORT_FAILED); } - + lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + "1827 Vport Enabled.\n"); return VPORT_OK; } @@ -431,8 +432,29 @@ lpfc_vport_delete(struct fc_vport *fc_vport) struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; struct lpfc_hba *phba = vport->phba; long timeout; - int rc = VPORT_ERROR; + if (vport->port_type == LPFC_PHYSICAL_PORT) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + "1812 vport_delete failed: Cannot delete " + "physical host\n"); + return VPORT_ERROR; + } + /* + * If we are not unloading the driver then prevent the vport_delete + * from happening until after this vport's discovery is finished. + */ + if (!(phba->pport->load_flag & FC_UNLOADING)) { + int check_count = 0; + while (check_count < ((phba->fc_ratov * 3) + 3) && + vport->port_state > LPFC_VPORT_FAILED && + vport->port_state < LPFC_VPORT_READY) { + check_count++; + msleep(1000); + } + if (vport->port_state > LPFC_VPORT_FAILED && + vport->port_state < LPFC_VPORT_READY) + return -EAGAIN; + } /* * This is a bit of a mess. We want to ensure the shost doesn't get * torn down until we're done with the embedded lpfc_vport structure. @@ -450,16 +472,9 @@ lpfc_vport_delete(struct fc_vport *fc_vport) */ if (!scsi_host_get(shost) || !scsi_host_get(shost)) return VPORT_INVAL; - - if (vport->port_type == LPFC_PHYSICAL_PORT) { - lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, - "%d:1812 vport_delete failed: Cannot delete " - "physical host\n", phba->brd_no); - goto out; - } - + spin_lock_irq(&phba->hbalock); vport->load_flag |= FC_UNLOADING; - + spin_unlock_irq(&phba->hbalock); kfree(vport->vname); lpfc_debugfs_terminate(vport); fc_remove_host(lpfc_shost_from_vport(vport)); @@ -511,13 +526,46 @@ skip_logo: spin_lock_irq(&phba->hbalock); list_del_init(&vport->listentry); spin_unlock_irq(&phba->hbalock); - - rc = VPORT_OK; -out: + lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, + "1828 Vport Deleted.\n"); scsi_host_put(shost); - return rc; + return VPORT_OK; } - EXPORT_SYMBOL(lpfc_vport_create); EXPORT_SYMBOL(lpfc_vport_delete); + +struct lpfc_vport ** +lpfc_create_vport_work_array(struct lpfc_hba *phba) +{ + struct lpfc_vport *port_iterator; + struct lpfc_vport **vports; + int index = 0; + vports = kzalloc(LPFC_MAX_VPORTS * sizeof(struct lpfc_vport *), + GFP_KERNEL); + if (vports == NULL) + return NULL; + spin_lock_irq(&phba->hbalock); + list_for_each_entry(port_iterator, &phba->port_list, listentry) { + if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) { + lpfc_printf_vlog(port_iterator, KERN_WARNING, LOG_VPORT, + "1801 Create vport work array FAILED: " + "cannot do scsi_host_get\n"); + continue; + } + vports[index++] = port_iterator; + } + spin_unlock_irq(&phba->hbalock); + return vports; +} + +void +lpfc_destroy_vport_work_array(struct lpfc_vport **vports) +{ + int i; + if (vports == NULL) + return; + for (i=0; vports[i] != NULL && i < LPFC_MAX_VPORTS; i++) + scsi_host_put(lpfc_shost_from_vport(vports[i])); + kfree(vports); +} diff --git a/drivers/scsi/lpfc/lpfc_vport.h b/drivers/scsi/lpfc/lpfc_vport.h index f223550f8cb..91da17751a3 100644 --- a/drivers/scsi/lpfc/lpfc_vport.h +++ b/drivers/scsi/lpfc/lpfc_vport.h @@ -88,6 +88,8 @@ int lpfc_vport_create(struct fc_vport *, bool); int lpfc_vport_delete(struct fc_vport *); int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *); int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint); +struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *); +void lpfc_destroy_vport_work_array(struct lpfc_vport **); /* * queuecommand VPORT-specific return codes. Specified in the host byte code. diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 3907f6718ed..da56163c30a 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -1753,6 +1753,14 @@ mega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len) *len = 0; + if (scsi_sg_count(cmd) == 1 && !adapter->has_64bit_addr) { + sg = scsi_sglist(cmd); + scb->dma_h_bulkdata = sg_dma_address(sg); + *buf = (u32)scb->dma_h_bulkdata; + *len = sg_dma_len(sg); + return 0; + } + scsi_for_each_sg(cmd, sg, sgcnt, idx) { if (adapter->has_64bit_addr) { scb->sgl64[idx].address = sg_dma_address(sg); diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index c46685a03a9..c6a53dccc16 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -454,7 +454,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); // Allocate the per driver initialization structure - adapter = kmalloc(sizeof(adapter_t), GFP_KERNEL); + adapter = kzalloc(sizeof(adapter_t), GFP_KERNEL); if (adapter == NULL) { con_log(CL_ANN, (KERN_WARNING @@ -462,7 +462,6 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto out_probe_one; } - memset(adapter, 0, sizeof(adapter_t)); // set up PCI related soft state and other pre-known parameters @@ -746,10 +745,9 @@ megaraid_init_mbox(adapter_t *adapter) * Allocate and initialize the init data structure for mailbox * controllers */ - raid_dev = kmalloc(sizeof(mraid_device_t), GFP_KERNEL); + raid_dev = kzalloc(sizeof(mraid_device_t), GFP_KERNEL); if (raid_dev == NULL) return -1; - memset(raid_dev, 0, sizeof(mraid_device_t)); /* * Attach the adapter soft state to raid device soft state @@ -1050,8 +1048,7 @@ megaraid_alloc_cmd_packets(adapter_t *adapter) * since the calling routine does not yet know the number of available * commands. */ - adapter->kscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_SCSI_CMDS, - GFP_KERNEL); + adapter->kscb_list = kcalloc(MBOX_MAX_SCSI_CMDS, sizeof(scb_t), GFP_KERNEL); if (adapter->kscb_list == NULL) { con_log(CL_ANN, (KERN_WARNING @@ -1059,7 +1056,6 @@ megaraid_alloc_cmd_packets(adapter_t *adapter) __LINE__)); goto out_free_ibuf; } - memset(adapter->kscb_list, 0, sizeof(scb_t) * MBOX_MAX_SCSI_CMDS); // memory allocation for our command packets if (megaraid_mbox_setup_dma_pools(adapter) != 0) { @@ -3495,8 +3491,7 @@ megaraid_cmm_register(adapter_t *adapter) int i; // Allocate memory for the base list of scb for management module. - adapter->uscb_list = kmalloc(sizeof(scb_t) * MBOX_MAX_USER_CMDS, - GFP_KERNEL); + adapter->uscb_list = kcalloc(MBOX_MAX_USER_CMDS, sizeof(scb_t), GFP_KERNEL); if (adapter->uscb_list == NULL) { con_log(CL_ANN, (KERN_WARNING @@ -3504,7 +3499,6 @@ megaraid_cmm_register(adapter_t *adapter) __LINE__)); return -1; } - memset(adapter->uscb_list, 0, sizeof(scb_t) * MBOX_MAX_USER_CMDS); // Initialize the synchronization parameters for resources for diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index 84d9c27133d..b6587a6d848 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -890,12 +890,11 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp) if (lld_adp->drvr_type != DRVRTYPE_MBOX) return (-EINVAL); - adapter = kmalloc(sizeof(mraid_mmadp_t), GFP_KERNEL); + adapter = kzalloc(sizeof(mraid_mmadp_t), GFP_KERNEL); if (!adapter) return -ENOMEM; - memset(adapter, 0, sizeof(mraid_mmadp_t)); adapter->unique_id = lld_adp->unique_id; adapter->drvr_type = lld_adp->drvr_type; diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index b7f2e613c90..ebb948c016b 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -1636,15 +1636,13 @@ static int megasas_alloc_cmds(struct megasas_instance *instance) * Allocate the dynamic array first and then allocate individual * commands. */ - instance->cmd_list = kmalloc(sizeof(struct megasas_cmd *) * max_cmd, - GFP_KERNEL); + instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL); if (!instance->cmd_list) { printk(KERN_DEBUG "megasas: out of memory\n"); return -ENOMEM; } - memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) * max_cmd); for (i = 0; i < max_cmd; i++) { instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd), diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c index d6ef22a941c..1bdddad4857 100644 --- a/drivers/scsi/mvme16x_scsi.c +++ b/drivers/scsi/mvme16x_scsi.c @@ -89,6 +89,7 @@ mvme16x_probe(struct device *dev) out_be32(0xfff4202c, v); } + dev_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -104,7 +105,7 @@ mvme16x_probe(struct device *dev) static __devexit int mvme16x_device_remove(struct device *dev) { - struct Scsi_Host *host = dev_to_shost(dev); + struct Scsi_Host *host = dev_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); /* Disable scsi chip ints */ diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index 7dd787f6ab2..fa481b515ea 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -2,9 +2,12 @@ # PCMCIA SCSI adapter configuration # -menu "PCMCIA SCSI adapter support" +menuconfig SCSI_LOWLEVEL_PCMCIA + bool "PCMCIA SCSI adapter support" depends on SCSI!=n && PCMCIA!=n +if SCSI_LOWLEVEL_PCMCIA && SCSI && PCMCIA + config PCMCIA_AHA152X tristate "Adaptec AHA152X PCMCIA support" depends on !64BIT @@ -77,4 +80,4 @@ config PCMCIA_SYM53C500 To compile this driver as a module, choose M here: the module will be called sym53c500_cs. -endmenu +endif # SCSI_LOWLEVEL_PCMCIA diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 370802d24ac..2dd0dc9a9ae 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -106,9 +106,8 @@ static int aha152x_probe(struct pcmcia_device *link) DEBUG(0, "aha152x_attach()\n"); /* Create new SCSI device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - memset(info, 0, sizeof(*info)); info->p_dev = link; link->priv = info; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index c6f8c6e65e0..445cfbbca9b 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1602,9 +1602,8 @@ static int nsp_cs_probe(struct pcmcia_device *link) nsp_dbg(NSP_DEBUG_INIT, "in"); /* Create new SCSI device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) { return -ENOMEM; } - memset(info, 0, sizeof(*info)); info->p_dev = link; link->priv = info; data->ScsiInfo = info; diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 697cfb76c3a..67c5a58d17d 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -162,10 +162,9 @@ static int qlogic_probe(struct pcmcia_device *link) DEBUG(0, "qlogic_attach()\n"); /* Create new SCSI device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - memset(info, 0, sizeof(*info)); info->p_dev = link; link->priv = info; link->io.NumPorts1 = 16; diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 2695b7187b2..961839ecfe8 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -875,10 +875,9 @@ SYM53C500_probe(struct pcmcia_device *link) DEBUG(0, "SYM53C500_attach()\n"); /* Create new SCSI device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - memset(info, 0, sizeof(*info)); info->p_dev = link; link->priv = info; link->io.NumPorts1 = 16; diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 2f1fa1eb7e9..67b6d76a6c8 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -1014,10 +1014,9 @@ static int __ppa_attach(struct parport *pb) int modes, ppb, ppb_hi; int err = -ENOMEM; - dev = kmalloc(sizeof(ppa_struct), GFP_KERNEL); + dev = kzalloc(sizeof(ppa_struct), GFP_KERNEL); if (!dev) return -ENOMEM; - memset(dev, 0, sizeof(ppa_struct)); dev->base = -1; dev->mode = PPA_AUTODETECT; dev->recon_tmo = PPA_RECON_TMO; diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c new file mode 100644 index 00000000000..b50f1e14f2a --- /dev/null +++ b/drivers/scsi/ps3rom.c @@ -0,0 +1,533 @@ +/* + * PS3 BD/DVD/CD-ROM Storage Driver + * + * Copyright (C) 2007 Sony Computer Entertainment Inc. + * Copyright 2007 Sony Corp. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/cdrom.h> +#include <linux/highmem.h> + +#include <scsi/scsi.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_dbg.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_host.h> + +#include <asm/lv1call.h> +#include <asm/ps3stor.h> + + +#define DEVICE_NAME "ps3rom" + +#define BOUNCE_SIZE (64*1024) + +#define PS3ROM_MAX_SECTORS (BOUNCE_SIZE / CD_FRAMESIZE) + + +struct ps3rom_private { + struct ps3_storage_device *dev; + struct scsi_cmnd *curr_cmd; +}; + + +#define LV1_STORAGE_SEND_ATAPI_COMMAND (1) + +struct lv1_atapi_cmnd_block { + u8 pkt[32]; /* packet command block */ + u32 pktlen; /* should be 12 for ATAPI 8020 */ + u32 blocks; + u32 block_size; + u32 proto; /* transfer mode */ + u32 in_out; /* transfer direction */ + u64 buffer; /* parameter except command block */ + u32 arglen; /* length above */ +}; + +enum lv1_atapi_proto { + NON_DATA_PROTO = 0, + PIO_DATA_IN_PROTO = 1, + PIO_DATA_OUT_PROTO = 2, + DMA_PROTO = 3 +}; + +enum lv1_atapi_in_out { + DIR_WRITE = 0, /* memory -> device */ + DIR_READ = 1 /* device -> memory */ +}; + + +static int ps3rom_slave_configure(struct scsi_device *scsi_dev) +{ + struct ps3rom_private *priv = shost_priv(scsi_dev->host); + struct ps3_storage_device *dev = priv->dev; + + dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %u, channel %u\n", __func__, + __LINE__, scsi_dev->id, scsi_dev->lun, scsi_dev->channel); + + /* + * ATAPI SFF8020 devices use MODE_SENSE_10, + * so we can prohibit MODE_SENSE_6 + */ + scsi_dev->use_10_for_ms = 1; + + /* we don't support {READ,WRITE}_6 */ + scsi_dev->use_10_for_rw = 1; + + return 0; +} + +/* + * copy data from device into scatter/gather buffer + */ +static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) +{ + int k, req_len, act_len, len, active; + void *kaddr; + struct scatterlist *sgpnt; + unsigned int buflen; + + buflen = cmd->request_bufflen; + if (!buflen) + return 0; + + if (!cmd->request_buffer) + return -1; + + sgpnt = cmd->request_buffer; + active = 1; + for (k = 0, req_len = 0, act_len = 0; k < cmd->use_sg; ++k, ++sgpnt) { + if (active) { + kaddr = kmap_atomic(sgpnt->page, KM_IRQ0); + len = sgpnt->length; + if ((req_len + len) > buflen) { + active = 0; + len = buflen - req_len; + } + memcpy(kaddr + sgpnt->offset, buf + req_len, len); + flush_kernel_dcache_page(sgpnt->page); + kunmap_atomic(kaddr, KM_IRQ0); + act_len += len; + } + req_len += sgpnt->length; + } + cmd->resid = req_len - act_len; + return 0; +} + +/* + * copy data from scatter/gather into device's buffer + */ +static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf) +{ + int k, req_len, len, fin; + void *kaddr; + struct scatterlist *sgpnt; + unsigned int buflen; + + buflen = cmd->request_bufflen; + if (!buflen) + return 0; + + if (!cmd->request_buffer) + return -1; + + sgpnt = cmd->request_buffer; + for (k = 0, req_len = 0, fin = 0; k < cmd->use_sg; ++k, ++sgpnt) { + kaddr = kmap_atomic(sgpnt->page, KM_IRQ0); + len = sgpnt->length; + if ((req_len + len) > buflen) { + len = buflen - req_len; + fin = 1; + } + memcpy(buf + req_len, kaddr + sgpnt->offset, len); + kunmap_atomic(kaddr, KM_IRQ0); + if (fin) + return req_len + len; + req_len += sgpnt->length; + } + return req_len; +} + +static int ps3rom_atapi_request(struct ps3_storage_device *dev, + struct scsi_cmnd *cmd) +{ + struct lv1_atapi_cmnd_block atapi_cmnd; + unsigned char opcode = cmd->cmnd[0]; + int res; + u64 lpar; + + dev_dbg(&dev->sbd.core, "%s:%u: send ATAPI command 0x%02x\n", __func__, + __LINE__, opcode); + + memset(&atapi_cmnd, 0, sizeof(struct lv1_atapi_cmnd_block)); + memcpy(&atapi_cmnd.pkt, cmd->cmnd, 12); + atapi_cmnd.pktlen = 12; + atapi_cmnd.block_size = 1; /* transfer size is block_size * blocks */ + atapi_cmnd.blocks = atapi_cmnd.arglen = cmd->request_bufflen; + atapi_cmnd.buffer = dev->bounce_lpar; + + switch (cmd->sc_data_direction) { + case DMA_FROM_DEVICE: + if (cmd->request_bufflen >= CD_FRAMESIZE) + atapi_cmnd.proto = DMA_PROTO; + else + atapi_cmnd.proto = PIO_DATA_IN_PROTO; + atapi_cmnd.in_out = DIR_READ; + break; + + case DMA_TO_DEVICE: + if (cmd->request_bufflen >= CD_FRAMESIZE) + atapi_cmnd.proto = DMA_PROTO; + else + atapi_cmnd.proto = PIO_DATA_OUT_PROTO; + atapi_cmnd.in_out = DIR_WRITE; + res = fetch_to_dev_buffer(cmd, dev->bounce_buf); + if (res < 0) + return DID_ERROR << 16; + break; + + default: + atapi_cmnd.proto = NON_DATA_PROTO; + break; + } + + lpar = ps3_mm_phys_to_lpar(__pa(&atapi_cmnd)); + res = lv1_storage_send_device_command(dev->sbd.dev_id, + LV1_STORAGE_SEND_ATAPI_COMMAND, + lpar, sizeof(atapi_cmnd), + atapi_cmnd.buffer, + atapi_cmnd.arglen, &dev->tag); + if (res == LV1_DENIED_BY_POLICY) { + dev_dbg(&dev->sbd.core, + "%s:%u: ATAPI command 0x%02x denied by policy\n", + __func__, __LINE__, opcode); + return DID_ERROR << 16; + } + + if (res) { + dev_err(&dev->sbd.core, + "%s:%u: ATAPI command 0x%02x failed %d\n", __func__, + __LINE__, opcode, res); + return DID_ERROR << 16; + } + + return 0; +} + +static inline unsigned int srb10_lba(const struct scsi_cmnd *cmd) +{ + return cmd->cmnd[2] << 24 | cmd->cmnd[3] << 16 | cmd->cmnd[4] << 8 | + cmd->cmnd[5]; +} + +static inline unsigned int srb10_len(const struct scsi_cmnd *cmd) +{ + return cmd->cmnd[7] << 8 | cmd->cmnd[8]; +} + +static int ps3rom_read_request(struct ps3_storage_device *dev, + struct scsi_cmnd *cmd, u32 start_sector, + u32 sectors) +{ + int res; + + dev_dbg(&dev->sbd.core, "%s:%u: read %u sectors starting at %u\n", + __func__, __LINE__, sectors, start_sector); + + res = lv1_storage_read(dev->sbd.dev_id, + dev->regions[dev->region_idx].id, start_sector, + sectors, 0, dev->bounce_lpar, &dev->tag); + if (res) { + dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__, + __LINE__, res); + return DID_ERROR << 16; + } + + return 0; +} + +static int ps3rom_write_request(struct ps3_storage_device *dev, + struct scsi_cmnd *cmd, u32 start_sector, + u32 sectors) +{ + int res; + + dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n", + __func__, __LINE__, sectors, start_sector); + + res = fetch_to_dev_buffer(cmd, dev->bounce_buf); + if (res < 0) + return DID_ERROR << 16; + + res = lv1_storage_write(dev->sbd.dev_id, + dev->regions[dev->region_idx].id, start_sector, + sectors, 0, dev->bounce_lpar, &dev->tag); + if (res) { + dev_err(&dev->sbd.core, "%s:%u: write failed %d\n", __func__, + __LINE__, res); + return DID_ERROR << 16; + } + + return 0; +} + +static int ps3rom_queuecommand(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) +{ + struct ps3rom_private *priv = shost_priv(cmd->device->host); + struct ps3_storage_device *dev = priv->dev; + unsigned char opcode; + int res; + +#ifdef DEBUG + scsi_print_command(cmd); +#endif + + priv->curr_cmd = cmd; + cmd->scsi_done = done; + + opcode = cmd->cmnd[0]; + /* + * While we can submit READ/WRITE SCSI commands as ATAPI commands, + * it's recommended for various reasons (performance, error handling, + * ...) to use lv1_storage_{read,write}() instead + */ + switch (opcode) { + case READ_10: + res = ps3rom_read_request(dev, cmd, srb10_lba(cmd), + srb10_len(cmd)); + break; + + case WRITE_10: + res = ps3rom_write_request(dev, cmd, srb10_lba(cmd), + srb10_len(cmd)); + break; + + default: + res = ps3rom_atapi_request(dev, cmd); + break; + } + + if (res) { + memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); + cmd->result = res; + cmd->sense_buffer[0] = 0x70; + cmd->sense_buffer[2] = ILLEGAL_REQUEST; + priv->curr_cmd = NULL; + cmd->scsi_done(cmd); + } + + return 0; +} + +static int decode_lv1_status(u64 status, unsigned char *sense_key, + unsigned char *asc, unsigned char *ascq) +{ + if (((status >> 24) & 0xff) != SAM_STAT_CHECK_CONDITION) + return -1; + + *sense_key = (status >> 16) & 0xff; + *asc = (status >> 8) & 0xff; + *ascq = status & 0xff; + return 0; +} + +static irqreturn_t ps3rom_interrupt(int irq, void *data) +{ + struct ps3_storage_device *dev = data; + struct Scsi_Host *host; + struct ps3rom_private *priv; + struct scsi_cmnd *cmd; + int res; + u64 tag, status; + unsigned char sense_key, asc, ascq; + + res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status); + /* + * status = -1 may mean that ATAPI transport completed OK, but + * ATAPI command itself resulted CHECK CONDITION + * so, upper layer should issue REQUEST_SENSE to check the sense data + */ + + if (tag != dev->tag) + dev_err(&dev->sbd.core, + "%s:%u: tag mismatch, got %lx, expected %lx\n", + __func__, __LINE__, tag, dev->tag); + + if (res) { + dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n", + __func__, __LINE__, res, status); + return IRQ_HANDLED; + } + + host = dev->sbd.core.driver_data; + priv = shost_priv(host); + cmd = priv->curr_cmd; + + if (!status) { + /* OK, completed */ + if (cmd->sc_data_direction == DMA_FROM_DEVICE) { + res = fill_from_dev_buffer(cmd, dev->bounce_buf); + if (res) { + cmd->result = DID_ERROR << 16; + goto done; + } + } + cmd->result = DID_OK << 16; + goto done; + } + + if (cmd->cmnd[0] == REQUEST_SENSE) { + /* SCSI spec says request sense should never get error */ + dev_err(&dev->sbd.core, "%s:%u: end error without autosense\n", + __func__, __LINE__); + cmd->result = DID_ERROR << 16 | SAM_STAT_CHECK_CONDITION; + goto done; + } + + if (decode_lv1_status(status, &sense_key, &asc, &ascq)) { + cmd->result = DID_ERROR << 16; + goto done; + } + + cmd->sense_buffer[0] = 0x70; + cmd->sense_buffer[2] = sense_key; + cmd->sense_buffer[7] = 16 - 6; + cmd->sense_buffer[12] = asc; + cmd->sense_buffer[13] = ascq; + cmd->result = SAM_STAT_CHECK_CONDITION; + +done: + priv->curr_cmd = NULL; + cmd->scsi_done(cmd); + return IRQ_HANDLED; +} + +static struct scsi_host_template ps3rom_host_template = { + .name = DEVICE_NAME, + .slave_configure = ps3rom_slave_configure, + .queuecommand = ps3rom_queuecommand, + .can_queue = 1, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .emulated = 1, /* only sg driver uses this */ + .max_sectors = PS3ROM_MAX_SECTORS, + .use_clustering = ENABLE_CLUSTERING, + .module = THIS_MODULE, +}; + + +static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev) +{ + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); + int error; + struct Scsi_Host *host; + struct ps3rom_private *priv; + + if (dev->blk_size != CD_FRAMESIZE) { + dev_err(&dev->sbd.core, + "%s:%u: cannot handle block size %lu\n", __func__, + __LINE__, dev->blk_size); + return -EINVAL; + } + + dev->bounce_size = BOUNCE_SIZE; + dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA); + if (!dev->bounce_buf) + return -ENOMEM; + + error = ps3stor_setup(dev, ps3rom_interrupt); + if (error) + goto fail_free_bounce; + + host = scsi_host_alloc(&ps3rom_host_template, + sizeof(struct ps3rom_private)); + if (!host) { + dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed\n", + __func__, __LINE__); + goto fail_teardown; + } + + priv = shost_priv(host); + dev->sbd.core.driver_data = host; + priv->dev = dev; + + /* One device/LUN per SCSI bus */ + host->max_id = 1; + host->max_lun = 1; + + error = scsi_add_host(host, &dev->sbd.core); + if (error) { + dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed %d\n", + __func__, __LINE__, error); + error = -ENODEV; + goto fail_host_put; + } + + scsi_scan_host(host); + return 0; + +fail_host_put: + scsi_host_put(host); + dev->sbd.core.driver_data = NULL; +fail_teardown: + ps3stor_teardown(dev); +fail_free_bounce: + kfree(dev->bounce_buf); + return error; +} + +static int ps3rom_remove(struct ps3_system_bus_device *_dev) +{ + struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); + struct Scsi_Host *host = dev->sbd.core.driver_data; + + scsi_remove_host(host); + ps3stor_teardown(dev); + scsi_host_put(host); + dev->sbd.core.driver_data = NULL; + kfree(dev->bounce_buf); + return 0; +} + +static struct ps3_system_bus_driver ps3rom = { + .match_id = PS3_MATCH_ID_STOR_ROM, + .core.name = DEVICE_NAME, + .core.owner = THIS_MODULE, + .probe = ps3rom_probe, + .remove = ps3rom_remove +}; + + +static int __init ps3rom_init(void) +{ + return ps3_system_bus_driver_register(&ps3rom); +} + +static void __exit ps3rom_exit(void) +{ + ps3_system_bus_driver_unregister(&ps3rom); +} + +module_init(ps3rom_init); +module_exit(ps3rom_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PS3 BD/DVD/CD-ROM Storage Driver"); +MODULE_AUTHOR("Sony Corporation"); +MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_ROM); diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 3eb2208675a..0f2a9f5d801 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -91,18 +91,20 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); - unsigned long flags; + int size = ha->nvram_size; + char *nvram_cache = ha->nvram; - if (!capable(CAP_SYS_ADMIN) || off != 0) + if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) return 0; + if (off + count > size) { + size -= off; + count = size; + } - /* Read NVRAM. */ - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->nvram_base, - ha->nvram_size); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + /* Read NVRAM data from cache. */ + memcpy(buf, &nvram_cache[off], count); - return ha->nvram_size; + return count; } static ssize_t @@ -119,7 +121,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, return 0; /* Checksum NVRAM. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { uint32_t *iter; uint32_t chksum; @@ -143,7 +145,9 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, /* Write NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); + ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); + ha->isp_ops->read_nvram(ha, (uint8_t *)&ha->nvram, ha->nvram_base, + count); spin_unlock_irqrestore(&ha->hardware_lock, flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); @@ -206,7 +210,7 @@ static struct bin_attribute sysfs_optrom_attr = { .name = "optrom", .mode = S_IRUSR | S_IWUSR, }, - .size = OPTROM_SIZE_24XX, + .size = 0, .read = qla2x00_sysfs_read_optrom, .write = qla2x00_sysfs_write_optrom, }; @@ -252,7 +256,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, } memset(ha->optrom_buffer, 0, ha->optrom_size); - ha->isp_ops.read_optrom(ha, ha->optrom_buffer, 0, + ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0, ha->optrom_size); break; case 2: @@ -275,7 +279,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, if (ha->optrom_state != QLA_SWRITING) break; - ha->isp_ops.write_optrom(ha, ha->optrom_buffer, 0, + ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0, ha->optrom_size); break; } @@ -298,17 +302,20 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, { struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); - unsigned long flags; + int size = ha->vpd_size; + char *vpd_cache = ha->vpd; - if (!capable(CAP_SYS_ADMIN) || off != 0) + if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) return 0; + if (off + count > size) { + size -= off; + count = size; + } - /* Read NVRAM. */ - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->vpd_base, ha->vpd_size); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + /* Read NVRAM data from cache. */ + memcpy(buf, &vpd_cache[off], count); - return ha->vpd_size; + return count; } static ssize_t @@ -325,7 +332,8 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, /* Write NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); - ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); + ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->vpd_base, count); + ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, ha->vpd_base, count); spin_unlock_irqrestore(&ha->hardware_lock, flags); return count; @@ -410,7 +418,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) int ret; for (iter = bin_file_entries; iter->name; iter++) { - if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) + if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) continue; ret = sysfs_create_bin_file(&host->shost_gendev.kobj, @@ -429,7 +437,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) struct sysfs_entry *iter; for (iter = bin_file_entries; iter->name; iter++) { - if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) + if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha)) continue; sysfs_remove_bin_file(&host->shost_gendev.kobj, @@ -437,7 +445,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) } if (ha->beacon_blink_led == 1) - ha->isp_ops.beacon_off(ha); + ha->isp_ops->beacon_off(ha); } /* Scsi_Host attributes. */ @@ -455,7 +463,7 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf) char fw_str[30]; return snprintf(buf, PAGE_SIZE, "%s\n", - ha->isp_ops.fw_version_str(ha, fw_str)); + ha->isp_ops->fw_version_str(ha, fw_str)); } static ssize_t @@ -507,7 +515,7 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf) char pci_info[30]; return snprintf(buf, PAGE_SIZE, "%s\n", - ha->isp_ops.pci_info_str(ha, pci_info)); + ha->isp_ops->pci_info_str(ha, pci_info)); } static ssize_t @@ -652,9 +660,9 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf, return -EINVAL; if (val) - rval = ha->isp_ops.beacon_on(ha); + rval = ha->isp_ops->beacon_on(ha); else - rval = ha->isp_ops.beacon_off(ha); + rval = ha->isp_ops->beacon_off(ha); if (rval != QLA_SUCCESS) count = 0; @@ -898,7 +906,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat = &ha->fc_host_stat; memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { rval = qla24xx_get_isp_stats(ha, (uint32_t *)&stat_buf, sizeof(stat_buf) / 4, mb_stat); } else if (atomic_read(&ha->loop_state) == LOOP_READY && diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 996c47a6307..c6680348b64 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -37,6 +37,121 @@ qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr) return ptr + (ha->response_q_length * sizeof(response_t)); } +static int +qla2xxx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, + uint32_t cram_size, uint32_t *ext_mem, void **nxt) +{ + int rval; + uint32_t cnt, stat, timer, risc_address, ext_mem_cnt; + uint16_t mb[4]; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + rval = QLA_SUCCESS; + risc_address = ext_mem_cnt = 0; + memset(mb, 0, sizeof(mb)); + + /* Code RAM. */ + risc_address = 0x20000; + WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED); + clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + + for (cnt = 0; cnt < cram_size / 4 && rval == QLA_SUCCESS; + cnt++, risc_address++) { + WRT_REG_WORD(®->mailbox1, LSW(risc_address)); + WRT_REG_WORD(®->mailbox8, MSW(risc_address)); + RD_REG_WORD(®->mailbox8); + WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); + + for (timer = 6000000; timer; timer--) { + /* Check for pending interrupts. */ + stat = RD_REG_DWORD(®->host_status); + if (stat & HSRX_RISC_INT) { + stat &= 0xff; + + if (stat == 0x1 || stat == 0x2 || + stat == 0x10 || stat == 0x11) { + set_bit(MBX_INTERRUPT, + &ha->mbx_cmd_flags); + + mb[0] = RD_REG_WORD(®->mailbox0); + mb[2] = RD_REG_WORD(®->mailbox2); + mb[3] = RD_REG_WORD(®->mailbox3); + + WRT_REG_DWORD(®->hccr, + HCCRX_CLR_RISC_INT); + RD_REG_DWORD(®->hccr); + break; + } + + /* Clear this intr; it wasn't a mailbox intr */ + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD(®->hccr); + } + udelay(5); + } + + if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { + rval = mb[0] & MBS_MASK; + code_ram[cnt] = htonl((mb[3] << 16) | mb[2]); + } else { + rval = QLA_FUNCTION_FAILED; + } + } + + if (rval == QLA_SUCCESS) { + /* External Memory. */ + risc_address = 0x100000; + ext_mem_cnt = ha->fw_memory_size - 0x100000 + 1; + WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED); + clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + } + for (cnt = 0; cnt < ext_mem_cnt && rval == QLA_SUCCESS; + cnt++, risc_address++) { + WRT_REG_WORD(®->mailbox1, LSW(risc_address)); + WRT_REG_WORD(®->mailbox8, MSW(risc_address)); + RD_REG_WORD(®->mailbox8); + WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); + + for (timer = 6000000; timer; timer--) { + /* Check for pending interrupts. */ + stat = RD_REG_DWORD(®->host_status); + if (stat & HSRX_RISC_INT) { + stat &= 0xff; + + if (stat == 0x1 || stat == 0x2 || + stat == 0x10 || stat == 0x11) { + set_bit(MBX_INTERRUPT, + &ha->mbx_cmd_flags); + + mb[0] = RD_REG_WORD(®->mailbox0); + mb[2] = RD_REG_WORD(®->mailbox2); + mb[3] = RD_REG_WORD(®->mailbox3); + + WRT_REG_DWORD(®->hccr, + HCCRX_CLR_RISC_INT); + RD_REG_DWORD(®->hccr); + break; + } + + /* Clear this intr; it wasn't a mailbox intr */ + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + RD_REG_DWORD(®->hccr); + } + udelay(5); + } + + if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { + rval = mb[0] & MBS_MASK; + ext_mem[cnt] = htonl((mb[3] << 16) | mb[2]); + } else { + rval = QLA_FUNCTION_FAILED; + } + } + + *nxt = rval == QLA_SUCCESS ? &ext_mem[cnt]: NULL; + return rval; +} + /** * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. * @ha: HA context @@ -633,11 +748,10 @@ void qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) { int rval; - uint32_t cnt, timer; + uint32_t cnt; uint32_t risc_address; - uint16_t mb[4], wd; + uint16_t mb0, wd; - uint32_t stat; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t __iomem *dmp_reg; uint32_t *iter_reg; @@ -645,10 +759,9 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) unsigned long flags; struct qla24xx_fw_dump *fw; uint32_t ext_mem_cnt; - void *eft; + void *nxt; risc_address = ext_mem_cnt = 0; - memset(mb, 0, sizeof(mb)); flags = 0; if (!hardware_locked) @@ -701,250 +814,236 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) /* Shadow registers. */ WRT_REG_DWORD(®->iobase_addr, 0x0F70); RD_REG_DWORD(®->iobase_addr); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0000000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[0] = htonl(RD_REG_DWORD(dmp_reg)); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0100000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[1] = htonl(RD_REG_DWORD(dmp_reg)); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0200000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[2] = htonl(RD_REG_DWORD(dmp_reg)); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0300000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[3] = htonl(RD_REG_DWORD(dmp_reg)); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0400000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[4] = htonl(RD_REG_DWORD(dmp_reg)); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0500000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[5] = htonl(RD_REG_DWORD(dmp_reg)); - - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); - WRT_REG_DWORD(dmp_reg, 0xB0600000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); - fw->shadow_reg[6] = htonl(RD_REG_DWORD(dmp_reg)); + WRT_REG_DWORD(®->iobase_select, 0xB0000000); + fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0100000); + fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0200000); + fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0300000); + fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0400000); + fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0500000); + fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0600000); + fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); /* Mailbox registers. */ - mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); + mbx_reg = ®->mailbox0; for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); /* Transfer sequence registers. */ iter_reg = fw->xseq_gp_reg; WRT_REG_DWORD(®->iobase_addr, 0xBF00); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xBF10); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xBF20); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xBF30); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xBF40); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xBF50); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xBF60); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xBF70); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xBFE0); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < sizeof(fw->xseq_0_reg) / 4; cnt++) fw->xseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xBFF0); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); /* Receive sequence registers. */ iter_reg = fw->rseq_gp_reg; WRT_REG_DWORD(®->iobase_addr, 0xFF00); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFF10); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFF20); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFF30); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFF40); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFF50); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFF60); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFF70); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFFD0); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < sizeof(fw->rseq_0_reg) / 4; cnt++) fw->rseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFFE0); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0xFFF0); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); /* Command DMA registers. */ WRT_REG_DWORD(®->iobase_addr, 0x7100); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); /* Queues. */ iter_reg = fw->req0_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7200); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 8; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xE4); + dmp_reg = ®->iobase_q; for (cnt = 0; cnt < 7; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); iter_reg = fw->resp0_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7300); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 8; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xE4); + dmp_reg = ®->iobase_q; for (cnt = 0; cnt < 7; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); iter_reg = fw->req1_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7400); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 8; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xE4); + dmp_reg = ®->iobase_q; for (cnt = 0; cnt < 7; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); /* Transmit DMA registers. */ iter_reg = fw->xmt0_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7600); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x7610); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); iter_reg = fw->xmt1_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7620); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x7630); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); iter_reg = fw->xmt2_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7640); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x7650); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); iter_reg = fw->xmt3_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7660); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x7670); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); iter_reg = fw->xmt4_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7680); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x7690); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x76A0); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) fw->xmt_data_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); @@ -952,221 +1051,221 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) /* Receive DMA registers. */ iter_reg = fw->rcvt0_data_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7700); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x7710); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); iter_reg = fw->rcvt1_data_dma_reg; WRT_REG_DWORD(®->iobase_addr, 0x7720); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x7730); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); /* RISC registers. */ iter_reg = fw->risc_gp_reg; WRT_REG_DWORD(®->iobase_addr, 0x0F00); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x0F10); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x0F20); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x0F30); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x0F40); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x0F50); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x0F60); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x0F70); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); /* Local memory controller registers. */ iter_reg = fw->lmc_reg; WRT_REG_DWORD(®->iobase_addr, 0x3000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x3010); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x3020); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x3030); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x3040); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x3050); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x3060); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); /* Fibre Protocol Module registers. */ iter_reg = fw->fpm_hdw_reg; WRT_REG_DWORD(®->iobase_addr, 0x4000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x4010); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x4020); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x4030); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x4040); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x4050); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x4060); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x4070); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x4080); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x4090); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x40A0); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x40B0); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); /* Frame Buffer registers. */ iter_reg = fw->fb_hdw_reg; WRT_REG_DWORD(®->iobase_addr, 0x6000); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x6010); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x6020); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x6030); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x6040); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x6100); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x6130); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x6150); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x6170); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x6190); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); WRT_REG_DWORD(®->iobase_addr, 0x61B0); - dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xC0); + dmp_reg = ®->iobase_window; for (cnt = 0; cnt < 16; cnt++) *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); @@ -1187,10 +1286,10 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) udelay(100); /* Wait for firmware to complete NVRAM accesses. */ - mb[0] = (uint32_t) RD_REG_WORD(®->mailbox0); - for (cnt = 10000 ; cnt && mb[0]; cnt--) { + mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); + for (cnt = 10000 ; cnt && mb0; cnt--) { udelay(5); - mb[0] = (uint32_t) RD_REG_WORD(®->mailbox0); + mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); barrier(); } @@ -1214,110 +1313,717 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) rval = QLA_FUNCTION_TIMEOUT; } - /* Memory. */ + if (rval == QLA_SUCCESS) + rval = qla2xxx_dump_memory(ha, fw->code_ram, + sizeof(fw->code_ram), fw->ext_mem, &nxt); + if (rval == QLA_SUCCESS) { - /* Code RAM. */ - risc_address = 0x20000; - WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED); - clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); + nxt = qla2xxx_copy_queues(ha, nxt); + if (ha->eft) + memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); } - for (cnt = 0; cnt < sizeof(fw->code_ram) / 4 && rval == QLA_SUCCESS; - cnt++, risc_address++) { - WRT_REG_WORD(®->mailbox1, LSW(risc_address)); - WRT_REG_WORD(®->mailbox8, MSW(risc_address)); - RD_REG_WORD(®->mailbox8); - WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); - for (timer = 6000000; timer; timer--) { - /* Check for pending interrupts. */ - stat = RD_REG_DWORD(®->host_status); - if (stat & HSRX_RISC_INT) { - stat &= 0xff; + if (rval != QLA_SUCCESS) { + qla_printk(KERN_WARNING, ha, + "Failed to dump firmware (%x)!!!\n", rval); + ha->fw_dumped = 0; - if (stat == 0x1 || stat == 0x2 || - stat == 0x10 || stat == 0x11) { - set_bit(MBX_INTERRUPT, - &ha->mbx_cmd_flags); + } else { + qla_printk(KERN_INFO, ha, + "Firmware dump saved to temp buffer (%ld/%p).\n", + ha->host_no, ha->fw_dump); + ha->fw_dumped = 1; + } - mb[0] = RD_REG_WORD(®->mailbox0); - mb[2] = RD_REG_WORD(®->mailbox2); - mb[3] = RD_REG_WORD(®->mailbox3); +qla24xx_fw_dump_failed: + if (!hardware_locked) + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} - WRT_REG_DWORD(®->hccr, - HCCRX_CLR_RISC_INT); - RD_REG_DWORD(®->hccr); - break; - } +void +qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) +{ + int rval; + uint32_t cnt; + uint32_t risc_address; + uint16_t mb0, wd; - /* Clear this intr; it wasn't a mailbox intr */ - WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - RD_REG_DWORD(®->hccr); - } - udelay(5); - } + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + uint32_t __iomem *dmp_reg; + uint32_t *iter_reg; + uint16_t __iomem *mbx_reg; + unsigned long flags; + struct qla25xx_fw_dump *fw; + uint32_t ext_mem_cnt; + void *nxt; - if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { - rval = mb[0] & MBS_MASK; - fw->code_ram[cnt] = htonl((mb[3] << 16) | mb[2]); - } else { - rval = QLA_FUNCTION_FAILED; + risc_address = ext_mem_cnt = 0; + flags = 0; + + if (!hardware_locked) + spin_lock_irqsave(&ha->hardware_lock, flags); + + if (!ha->fw_dump) { + qla_printk(KERN_WARNING, ha, + "No buffer available for dump!!!\n"); + goto qla25xx_fw_dump_failed; + } + + if (ha->fw_dumped) { + qla_printk(KERN_WARNING, ha, + "Firmware has been previously dumped (%p) -- ignoring " + "request...\n", ha->fw_dump); + goto qla25xx_fw_dump_failed; + } + fw = &ha->fw_dump->isp.isp25; + qla2xxx_prep_dump(ha, ha->fw_dump); + + rval = QLA_SUCCESS; + fw->host_status = htonl(RD_REG_DWORD(®->host_status)); + + /* Pause RISC. */ + if ((RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0) { + WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET | + HCCRX_CLR_HOST_INT); + RD_REG_DWORD(®->hccr); /* PCI Posting. */ + WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); + for (cnt = 30000; + (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) + udelay(100); + else + rval = QLA_FUNCTION_TIMEOUT; } } if (rval == QLA_SUCCESS) { - /* External Memory. */ - risc_address = 0x100000; - ext_mem_cnt = ha->fw_memory_size - 0x100000 + 1; - WRT_REG_WORD(®->mailbox0, MBC_READ_RAM_EXTENDED); - clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); - } - for (cnt = 0; cnt < ext_mem_cnt && rval == QLA_SUCCESS; - cnt++, risc_address++) { - WRT_REG_WORD(®->mailbox1, LSW(risc_address)); - WRT_REG_WORD(®->mailbox8, MSW(risc_address)); - RD_REG_WORD(®->mailbox8); - WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT); + /* Host interface registers. */ + dmp_reg = (uint32_t __iomem *)(reg + 0); + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - for (timer = 6000000; timer; timer--) { - /* Check for pending interrupts. */ - stat = RD_REG_DWORD(®->host_status); - if (stat & HSRX_RISC_INT) { - stat &= 0xff; + /* Disable interrupts. */ + WRT_REG_DWORD(®->ictrl, 0); + RD_REG_DWORD(®->ictrl); - if (stat == 0x1 || stat == 0x2 || - stat == 0x10 || stat == 0x11) { - set_bit(MBX_INTERRUPT, - &ha->mbx_cmd_flags); + /* Shadow registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x0F70); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_select, 0xB0000000); + fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); - mb[0] = RD_REG_WORD(®->mailbox0); - mb[2] = RD_REG_WORD(®->mailbox2); - mb[3] = RD_REG_WORD(®->mailbox3); + WRT_REG_DWORD(®->iobase_select, 0xB0100000); + fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); - WRT_REG_DWORD(®->hccr, - HCCRX_CLR_RISC_INT); - RD_REG_DWORD(®->hccr); - break; - } + WRT_REG_DWORD(®->iobase_select, 0xB0200000); + fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); - /* Clear this intr; it wasn't a mailbox intr */ - WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - RD_REG_DWORD(®->hccr); - } + WRT_REG_DWORD(®->iobase_select, 0xB0300000); + fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0400000); + fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0500000); + fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0600000); + fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0700000); + fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0800000); + fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0900000); + fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0A00000); + fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + /* RISC I/O register. */ + WRT_REG_DWORD(®->iobase_addr, 0x0010); + RD_REG_DWORD(®->iobase_addr); + fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window)); + + /* Mailbox registers. */ + mbx_reg = ®->mailbox0; + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); + + /* Transfer sequence registers. */ + iter_reg = fw->xseq_gp_reg; + WRT_REG_DWORD(®->iobase_addr, 0xBF00); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBF10); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBF20); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBF30); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBF40); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBF50); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBF60); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBF70); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->xseq_0_reg; + WRT_REG_DWORD(®->iobase_addr, 0xBFC0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBFD0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBFE0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xBFF0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) + fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Receive sequence registers. */ + iter_reg = fw->rseq_gp_reg; + WRT_REG_DWORD(®->iobase_addr, 0xFF00); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFF10); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFF20); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFF30); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFF40); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFF50); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFF60); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFF70); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->rseq_0_reg; + WRT_REG_DWORD(®->iobase_addr, 0xFFC0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFFD0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFFE0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) + fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xFFF0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) + fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Auxiliary sequence registers. */ + iter_reg = fw->aseq_gp_reg; + WRT_REG_DWORD(®->iobase_addr, 0xB000); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB010); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB020); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB030); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB040); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB050); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB060); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB070); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->aseq_0_reg; + WRT_REG_DWORD(®->iobase_addr, 0xB0C0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB0D0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB0E0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < sizeof(fw->aseq_1_reg) / 4; cnt++) + fw->aseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0xB0F0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < sizeof(fw->aseq_2_reg) / 4; cnt++) + fw->aseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Command DMA registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x7100); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) + fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Queues. */ + iter_reg = fw->req0_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7200); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 8; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->resp0_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7300); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 8; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->req1_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7400); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 8; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Transmit DMA registers. */ + iter_reg = fw->xmt0_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7600); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x7610); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->xmt1_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7620); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x7630); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->xmt2_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7640); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x7650); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->xmt3_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7660); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x7670); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->xmt4_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7680); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x7690); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x76A0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) + fw->xmt_data_dma_reg[cnt] = + htonl(RD_REG_DWORD(dmp_reg++)); + + /* Receive DMA registers. */ + iter_reg = fw->rcvt0_data_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7700); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x7710); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->rcvt1_data_dma_reg; + WRT_REG_DWORD(®->iobase_addr, 0x7720); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x7730); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* RISC registers. */ + iter_reg = fw->risc_gp_reg; + WRT_REG_DWORD(®->iobase_addr, 0x0F00); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x0F10); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x0F20); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x0F30); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x0F40); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x0F50); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x0F60); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x0F70); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Local memory controller registers. */ + iter_reg = fw->lmc_reg; + WRT_REG_DWORD(®->iobase_addr, 0x3000); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x3010); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x3020); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x3030); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x3040); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x3050); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x3060); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x3070); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Fibre Protocol Module registers. */ + iter_reg = fw->fpm_hdw_reg; + WRT_REG_DWORD(®->iobase_addr, 0x4000); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x4010); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x4020); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x4030); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x4040); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x4050); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x4060); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x4070); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x4080); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x4090); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x40A0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x40B0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Frame Buffer registers. */ + iter_reg = fw->fb_hdw_reg; + WRT_REG_DWORD(®->iobase_addr, 0x6000); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6010); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6020); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6030); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6040); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6100); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6130); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6150); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6170); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6190); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x61B0); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + WRT_REG_DWORD(®->iobase_addr, 0x6F00); + dmp_reg = ®->iobase_window; + for (cnt = 0; cnt < 16; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Reset RISC. */ + WRT_REG_DWORD(®->ctrl_status, + CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_DWORD(®->ctrl_status) & + CSRX_DMA_ACTIVE) == 0) + break; + + udelay(10); + } + + WRT_REG_DWORD(®->ctrl_status, + CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); + pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); + + udelay(100); + /* Wait for firmware to complete NVRAM accesses. */ + mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); + for (cnt = 10000 ; cnt && mb0; cnt--) { udelay(5); + mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); + barrier(); } - if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) { - rval = mb[0] & MBS_MASK; - fw->ext_mem[cnt] = htonl((mb[3] << 16) | mb[2]); - } else { - rval = QLA_FUNCTION_FAILED; + /* Wait for soft-reset to complete. */ + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_DWORD(®->ctrl_status) & + CSRX_ISP_SOFT_RESET) == 0) + break; + + udelay(10); } + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); + RD_REG_DWORD(®->hccr); /* PCI Posting. */ } + for (cnt = 30000; RD_REG_WORD(®->mailbox0) != 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) + udelay(100); + else + rval = QLA_FUNCTION_TIMEOUT; + } + + if (rval == QLA_SUCCESS) + rval = qla2xxx_dump_memory(ha, fw->code_ram, + sizeof(fw->code_ram), fw->ext_mem, &nxt); + if (rval == QLA_SUCCESS) { - eft = qla2xxx_copy_queues(ha, &fw->ext_mem[cnt]); + nxt = qla2xxx_copy_queues(ha, nxt); if (ha->eft) - memcpy(eft, ha->eft, ntohl(ha->fw_dump->eft_size)); + memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); } if (rval != QLA_SUCCESS) { @@ -1332,7 +2038,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) ha->fw_dumped = 1; } -qla24xx_fw_dump_failed: +qla25xx_fw_dump_failed: if (!hardware_locked) spin_unlock_irqrestore(&ha->hardware_lock, flags); } @@ -1344,21 +2050,18 @@ qla24xx_fw_dump_failed: void qla2x00_dump_regs(scsi_qla_host_t *ha) { + int i; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; + uint16_t __iomem *mbx_reg; + + mbx_reg = IS_FWI2_CAPABLE(ha) ? ®24->mailbox0: + MAILBOX_REG(ha, reg, 0); printk("Mailbox registers:\n"); - printk("scsi(%ld): mbox 0 0x%04x \n", - ha->host_no, RD_MAILBOX_REG(ha, reg, 0)); - printk("scsi(%ld): mbox 1 0x%04x \n", - ha->host_no, RD_MAILBOX_REG(ha, reg, 1)); - printk("scsi(%ld): mbox 2 0x%04x \n", - ha->host_no, RD_MAILBOX_REG(ha, reg, 2)); - printk("scsi(%ld): mbox 3 0x%04x \n", - ha->host_no, RD_MAILBOX_REG(ha, reg, 3)); - printk("scsi(%ld): mbox 4 0x%04x \n", - ha->host_no, RD_MAILBOX_REG(ha, reg, 4)); - printk("scsi(%ld): mbox 5 0x%04x \n", - ha->host_no, RD_MAILBOX_REG(ha, reg, 5)); + for (i = 0; i < 6; i++) + printk("scsi(%ld): mbox %d 0x%04x \n", ha->host_no, i, + RD_REG_WORD(mbx_reg++)); } diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 49dffeb7851..cca4b0d8253 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -213,6 +213,43 @@ struct qla24xx_fw_dump { uint32_t ext_mem[1]; }; +struct qla25xx_fw_dump { + uint32_t host_status; + uint32_t host_reg[32]; + uint32_t shadow_reg[11]; + uint32_t risc_io_reg; + uint16_t mailbox_reg[32]; + uint32_t xseq_gp_reg[128]; + uint32_t xseq_0_reg[48]; + uint32_t xseq_1_reg[16]; + uint32_t rseq_gp_reg[128]; + uint32_t rseq_0_reg[32]; + uint32_t rseq_1_reg[16]; + uint32_t rseq_2_reg[16]; + uint32_t aseq_gp_reg[128]; + uint32_t aseq_0_reg[32]; + uint32_t aseq_1_reg[16]; + uint32_t aseq_2_reg[16]; + uint32_t cmd_dma_reg[16]; + uint32_t req0_dma_reg[15]; + uint32_t resp0_dma_reg[15]; + uint32_t req1_dma_reg[15]; + uint32_t xmt0_dma_reg[32]; + uint32_t xmt1_dma_reg[32]; + uint32_t xmt2_dma_reg[32]; + uint32_t xmt3_dma_reg[32]; + uint32_t xmt4_dma_reg[32]; + uint32_t xmt_data_dma_reg[16]; + uint32_t rcvt0_data_dma_reg[32]; + uint32_t rcvt1_data_dma_reg[32]; + uint32_t risc_gp_reg[128]; + uint32_t lmc_reg[128]; + uint32_t fpm_hdw_reg[192]; + uint32_t fb_hdw_reg[192]; + uint32_t code_ram[0x2000]; + uint32_t ext_mem[1]; +}; + #define EFT_NUM_BUFFERS 4 #define EFT_BYTES_PER_BUFFER 0x4000 #define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS)) @@ -246,5 +283,6 @@ struct qla2xxx_fw_dump { struct qla2100_fw_dump isp21; struct qla2300_fw_dump isp23; struct qla24xx_fw_dump isp24; + struct qla25xx_fw_dump isp25; } isp; }; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index a1ca590ba44..c1964866a42 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1502,7 +1502,6 @@ typedef struct { uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; uint8_t fabric_port_name[WWN_SIZE]; - uint16_t fp_speeds; uint16_t fp_speed; } sw_info_t; @@ -1711,6 +1710,14 @@ struct ct_fdmi_hba_attributes { #define FDMI_PORT_OS_DEVICE_NAME 5 #define FDMI_PORT_HOST_NAME 6 +#define FDMI_PORT_SPEED_1GB 0x1 +#define FDMI_PORT_SPEED_2GB 0x2 +#define FDMI_PORT_SPEED_10GB 0x4 +#define FDMI_PORT_SPEED_4GB 0x8 +#define FDMI_PORT_SPEED_8GB 0x10 +#define FDMI_PORT_SPEED_16GB 0x20 +#define FDMI_PORT_SPEED_UNKNOWN 0x8000 + struct ct_fdmi_port_attr { uint16_t type; uint16_t len; @@ -2201,6 +2208,7 @@ typedef struct scsi_qla_host { #define SWITCH_FOUND BIT_3 #define DFLG_NO_CABLE BIT_4 +#define PCI_DEVICE_ID_QLOGIC_ISP2532 0x2532 uint32_t device_type; #define DT_ISP2100 BIT_0 #define DT_ISP2200 BIT_1 @@ -2213,8 +2221,11 @@ typedef struct scsi_qla_host { #define DT_ISP2432 BIT_8 #define DT_ISP5422 BIT_9 #define DT_ISP5432 BIT_10 -#define DT_ISP_LAST (DT_ISP5432 << 1) +#define DT_ISP2532 BIT_11 +#define DT_ISP_LAST (DT_ISP2532 << 1) +#define DT_IIDMA BIT_26 +#define DT_FWI2 BIT_27 #define DT_ZIO_SUPPORTED BIT_28 #define DT_OEM_001 BIT_29 #define DT_ISP2200A BIT_30 @@ -2232,12 +2243,16 @@ typedef struct scsi_qla_host { #define IS_QLA2432(ha) (DT_MASK(ha) & DT_ISP2432) #define IS_QLA5422(ha) (DT_MASK(ha) & DT_ISP5422) #define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432) +#define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532) #define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \ IS_QLA6312(ha) || IS_QLA6322(ha)) #define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha)) #define IS_QLA54XX(ha) (IS_QLA5422(ha) || IS_QLA5432(ha)) +#define IS_QLA25XX(ha) (IS_QLA2532(ha)) +#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA) +#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2) #define IS_ZIO_SUPPORTED(ha) ((ha)->device_type & DT_ZIO_SUPPORTED) #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001) #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS) @@ -2274,7 +2289,7 @@ typedef struct scsi_qla_host { uint16_t rsp_ring_index; /* Current index. */ uint16_t response_q_length; - struct isp_operations isp_ops; + struct isp_operations *isp_ops; /* Outstandings ISP commands. */ srb_t *outstanding_cmds[MAX_OUTSTANDING_COMMANDS]; @@ -2298,6 +2313,7 @@ typedef struct scsi_qla_host { #define PORT_SPEED_1GB 0x00 #define PORT_SPEED_2GB 0x01 #define PORT_SPEED_4GB 0x03 +#define PORT_SPEED_8GB 0x04 uint16_t link_data_rate; /* F/W operating speed */ uint8_t current_topology; @@ -2323,10 +2339,14 @@ typedef struct scsi_qla_host { uint8_t serial2; /* NVRAM configuration data */ +#define MAX_NVRAM_SIZE 4096 +#define VPD_OFFSET MAX_NVRAM_SIZE / 2 uint16_t nvram_size; uint16_t nvram_base; + void *nvram; uint16_t vpd_size; uint16_t vpd_base; + void *vpd; uint16_t loop_reset_delay; uint8_t retry_count; @@ -2564,6 +2584,7 @@ typedef struct scsi_qla_host { #define OPTROM_SIZE_2300 0x20000 #define OPTROM_SIZE_2322 0x100000 #define OPTROM_SIZE_24XX 0x100000 +#define OPTROM_SIZE_25XX 0x200000 #include "qla_gbl.h" #include "qla_dbg.h" diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 63a11fef5d1..99fe49618d6 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -8,14 +8,17 @@ #define __QLA_FW_H #define MBS_CHECKSUM_ERROR 0x4010 +#define MBS_INVALID_PRODUCT_KEY 0x4020 /* * Firmware Options. */ #define FO1_ENABLE_PUREX BIT_10 #define FO1_DISABLE_LED_CTRL BIT_6 +#define FO1_ENABLE_8016 BIT_0 #define FO2_ENABLE_SEL_CLASS2 BIT_5 #define FO3_NO_ABTS_ON_LINKDOWN BIT_14 +#define FO3_HOLD_STS_IOCB BIT_12 /* * Port Database structure definition for ISP 24xx. @@ -341,7 +344,9 @@ struct init_cb_24xx { * BIT 10 = Reserved * BIT 11 = Enable FC-SP Security * BIT 12 = FC Tape Enable - * BIT 13-31 = Reserved + * BIT 13 = Reserved + * BIT 14 = Enable Target PRLI Control + * BIT 15-31 = Reserved */ uint32_t firmware_options_2; @@ -363,7 +368,8 @@ struct init_cb_24xx { * BIT 13 = Data Rate bit 0 * BIT 14 = Data Rate bit 1 * BIT 15 = Data Rate bit 2 - * BIT 16-31 = Reserved + * BIT 16 = Enable 75 ohm Termination Select + * BIT 17-31 = Reserved */ uint32_t firmware_options_3; @@ -435,6 +441,7 @@ struct cmd_type_7 { #define TMF_LUN_RESET BIT_12 #define TMF_CLEAR_TASK_SET BIT_10 #define TMF_ABORT_TASK_SET BIT_9 +#define TMF_DSD_LIST_ENABLE BIT_2 #define TMF_READ_DATA BIT_1 #define TMF_WRITE_DATA BIT_0 @@ -589,7 +596,7 @@ struct els_entry_24xx { #define EST_SOFI3 (1 << 4) #define EST_SOFI2 (3 << 4) - uint32_t rx_xchg_address[2]; /* Receive exchange address. */ + uint32_t rx_xchg_address; /* Receive exchange address. */ uint16_t rx_dsd_count; uint8_t opcode; @@ -650,6 +657,7 @@ struct logio_entry_24xx { uint16_t control_flags; /* Control flags. */ /* Modifiers. */ +#define LCF_INCLUDE_SNS BIT_10 /* Include SNS (FFFFFC) during LOGO. */ #define LCF_FCP2_OVERRIDE BIT_9 /* Set/Reset word 3 of PRLI. */ #define LCF_CLASS_2 BIT_8 /* Enable class 2 during PLOGI. */ #define LCF_FREE_NPORT BIT_7 /* Release NPORT handle after LOGO. */ @@ -779,6 +787,15 @@ struct device_reg_24xx { #define FA_RISC_CODE_ADDR 0x20000 #define FA_RISC_CODE_SEGMENTS 2 +#define FA_FW_AREA_ADDR 0x40000 +#define FA_VPD_NVRAM_ADDR 0x48000 +#define FA_FEATURE_ADDR 0x4C000 +#define FA_FLASH_DESCR_ADDR 0x50000 +#define FA_HW_EVENT_ADDR 0x54000 +#define FA_BOOT_LOG_ADDR 0x58000 +#define FA_FW_DUMP0_ADDR 0x60000 +#define FA_FW_DUMP1_ADDR 0x70000 + uint32_t flash_data; /* Flash/NVRAM BIOS data. */ uint32_t ctrl_status; /* Control/Status. */ @@ -859,10 +876,13 @@ struct device_reg_24xx { #define HCCRX_CLR_RISC_INT 0xA0000000 uint32_t gpiod; /* GPIO Data register. */ + /* LED update mask. */ #define GPDX_LED_UPDATE_MASK (BIT_20|BIT_19|BIT_18) /* Data update mask. */ #define GPDX_DATA_UPDATE_MASK (BIT_17|BIT_16) + /* Data update mask. */ +#define GPDX_DATA_UPDATE_2_MASK (BIT_28|BIT_27|BIT_26|BIT_17|BIT_16) /* LED control mask. */ #define GPDX_LED_COLOR_MASK (BIT_4|BIT_3|BIT_2) /* LED bit values. Color names as @@ -877,6 +897,8 @@ struct device_reg_24xx { uint32_t gpioe; /* GPIO Enable register. */ /* Enable update mask. */ #define GPEX_ENABLE_UPDATE_MASK (BIT_17|BIT_16) + /* Enable update mask. */ +#define GPEX_ENABLE_UPDATE_2_MASK (BIT_28|BIT_27|BIT_26|BIT_17|BIT_16) /* Enable. */ #define GPEX_ENABLE (BIT_1|BIT_0) @@ -916,6 +938,14 @@ struct device_reg_24xx { uint16_t mailbox29; uint16_t mailbox30; uint16_t mailbox31; + + uint32_t iobase_window; + uint32_t unused_4[8]; /* Gap. */ + uint32_t iobase_q; + uint32_t unused_5[2]; /* Gap. */ + uint32_t iobase_select; + uint32_t unused_6[2]; /* Gap. */ + uint32_t iobase_sdata; }; /* MID Support ***************************************************************/ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index b44eff2803c..aa1e4115228 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -17,6 +17,7 @@ extern int qla2x00_initialize_adapter(scsi_qla_host_t *); extern int qla2100_pci_config(struct scsi_qla_host *); extern int qla2300_pci_config(struct scsi_qla_host *); extern int qla24xx_pci_config(scsi_qla_host_t *); +extern int qla25xx_pci_config(scsi_qla_host_t *); extern void qla2x00_reset_chip(struct scsi_qla_host *); extern void qla24xx_reset_chip(struct scsi_qla_host *); extern int qla2x00_chip_diag(struct scsi_qla_host *); @@ -281,6 +282,10 @@ extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, uint32_t); extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, uint32_t); +extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, + uint32_t); +extern int qla25xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t, + uint32_t); extern int qla2x00_beacon_on(struct scsi_qla_host *); extern int qla2x00_beacon_off(struct scsi_qla_host *); @@ -307,6 +312,7 @@ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); extern void qla2100_fw_dump(scsi_qla_host_t *, int); extern void qla2300_fw_dump(scsi_qla_host_t *, int); extern void qla24xx_fw_dump(scsi_qla_host_t *, int); +extern void qla25xx_fw_dump(scsi_qla_host_t *, int); extern void qla2x00_dump_regs(scsi_qla_host_t *); extern void qla2x00_dump_buffer(uint8_t *, uint32_t); extern void qla2x00_print_scsi_cmd(struct scsi_cmnd *); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index a086b3f0df6..a7e23583f89 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -127,7 +127,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *ha, ms_iocb_entry_t *ms_pkt, DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n", ha->host_no, routine, ms_pkt->entry_status)); } else { - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) comp_status = le16_to_cpu( ((struct ct_entry_24xx *)ms_pkt)->comp_status); else @@ -180,7 +180,8 @@ qla2x00_ga_nxt(scsi_qla_host_t *ha, fc_port_t *fcport) /* Issue GA_NXT */ /* Prepare common MS IOCB */ - ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GA_NXT_REQ_SIZE, GA_NXT_RSP_SIZE); + ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GA_NXT_REQ_SIZE, + GA_NXT_RSP_SIZE); /* Prepare CT request */ ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GA_NXT_CMD, @@ -266,7 +267,8 @@ qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list) /* Issue GID_PT */ /* Prepare common MS IOCB */ - ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GID_PT_REQ_SIZE, GID_PT_RSP_SIZE); + ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GID_PT_REQ_SIZE, + GID_PT_RSP_SIZE); /* Prepare CT request */ ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, GID_PT_CMD, @@ -293,6 +295,8 @@ qla2x00_gid_pt(scsi_qla_host_t *ha, sw_info_t *list) list[i].d_id.b.domain = gid_data->port_id[0]; list[i].d_id.b.area = gid_data->port_id[1]; list[i].d_id.b.al_pa = gid_data->port_id[2]; + memset(list[i].fabric_port_name, 0, WWN_SIZE); + list[i].fp_speed = PORT_SPEED_UNKNOWN; /* Last one exit. */ if (gid_data->control_byte & BIT_7) { @@ -338,7 +342,7 @@ qla2x00_gpn_id(scsi_qla_host_t *ha, sw_info_t *list) for (i = 0; i < MAX_FIBRE_DEVICES; i++) { /* Issue GPN_ID */ /* Prepare common MS IOCB */ - ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GPN_ID_REQ_SIZE, + ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GPN_ID_REQ_SIZE, GPN_ID_RSP_SIZE); /* Prepare CT request */ @@ -399,7 +403,7 @@ qla2x00_gnn_id(scsi_qla_host_t *ha, sw_info_t *list) for (i = 0; i < MAX_FIBRE_DEVICES; i++) { /* Issue GNN_ID */ /* Prepare common MS IOCB */ - ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GNN_ID_REQ_SIZE, + ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GNN_ID_REQ_SIZE, GNN_ID_RSP_SIZE); /* Prepare CT request */ @@ -473,7 +477,8 @@ qla2x00_rft_id(scsi_qla_host_t *ha) /* Issue RFT_ID */ /* Prepare common MS IOCB */ - ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFT_ID_REQ_SIZE, RFT_ID_RSP_SIZE); + ms_pkt = ha->isp_ops->prep_ms_iocb(ha, RFT_ID_REQ_SIZE, + RFT_ID_RSP_SIZE); /* Prepare CT request */ ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFT_ID_CMD, @@ -528,7 +533,8 @@ qla2x00_rff_id(scsi_qla_host_t *ha) /* Issue RFF_ID */ /* Prepare common MS IOCB */ - ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RFF_ID_REQ_SIZE, RFF_ID_RSP_SIZE); + ms_pkt = ha->isp_ops->prep_ms_iocb(ha, RFF_ID_REQ_SIZE, + RFF_ID_RSP_SIZE); /* Prepare CT request */ ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RFF_ID_CMD, @@ -582,7 +588,8 @@ qla2x00_rnn_id(scsi_qla_host_t *ha) /* Issue RNN_ID */ /* Prepare common MS IOCB */ - ms_pkt = ha->isp_ops.prep_ms_iocb(ha, RNN_ID_REQ_SIZE, RNN_ID_RSP_SIZE); + ms_pkt = ha->isp_ops->prep_ms_iocb(ha, RNN_ID_REQ_SIZE, + RNN_ID_RSP_SIZE); /* Prepare CT request */ ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RNN_ID_CMD, @@ -645,7 +652,7 @@ qla2x00_rsnn_nn(scsi_qla_host_t *ha) /* Issue RSNN_NN */ /* Prepare common MS IOCB */ /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops.prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE); + ms_pkt = ha->isp_ops->prep_ms_iocb(ha, 0, RSNN_NN_RSP_SIZE); /* Prepare CT request */ ct_req = qla2x00_prep_ct_req(&ha->ct_sns->p.req, RSNN_NN_CMD, @@ -1102,7 +1109,7 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *ha) if (ha->flags.management_server_logged_in) return ret; - ha->isp_ops.fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa, + ha->isp_ops->fabric_login(ha, ha->mgmt_svr_loop_id, 0xff, 0xff, 0xfa, mb, BIT_1); if (mb[0] != MBS_COMMAND_COMPLETE) { DEBUG2_13(printk("%s(%ld): Failed MANAGEMENT_SERVER login: " @@ -1198,7 +1205,7 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size) ms_iocb_entry_t *ms_pkt = ha->ms_iocb; struct ct_entry_24xx *ct_pkt = (struct ct_entry_24xx *)ha->ms_iocb; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { ct_pkt->cmd_byte_count = cpu_to_le32(req_size); ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count; } else { @@ -1253,7 +1260,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *ha) /* Issue RHBA */ /* Prepare common MS IOCB */ /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE); + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(ha, 0, RHBA_RSP_SIZE); /* Prepare CT request */ ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RHBA_CMD, @@ -1373,7 +1380,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *ha) /* Firmware version */ eiter = (struct ct_fdmi_hba_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION); - ha->isp_ops.fw_version_str(ha, eiter->a.fw_version); + ha->isp_ops->fw_version_str(ha, eiter->a.fw_version); alen = strlen(eiter->a.fw_version); alen += (alen & 3) ? (4 - (alen & 3)) : 4; eiter->len = cpu_to_be16(4 + alen); @@ -1439,7 +1446,7 @@ qla2x00_fdmi_dhba(scsi_qla_host_t *ha) /* Issue RPA */ /* Prepare common MS IOCB */ - ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE, + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(ha, DHBA_REQ_SIZE, DHBA_RSP_SIZE); /* Prepare CT request */ @@ -1497,7 +1504,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) /* Issue RPA */ /* Prepare common MS IOCB */ /* Request size adjusted after CT preparation */ - ms_pkt = ha->isp_ops.prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE); + ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(ha, 0, RPA_RSP_SIZE); /* Prepare CT request */ ct_req = qla2x00_prep_ct_fdmi_req(&ha->ct_sns->p.req, RPA_CMD, @@ -1527,12 +1534,20 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED); eiter->len = __constant_cpu_to_be16(4 + 4); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) - eiter->a.sup_speed = __constant_cpu_to_be32(4); + if (IS_QLA25XX(ha)) + eiter->a.sup_speed = __constant_cpu_to_be32( + FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB| + FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB); + else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + eiter->a.sup_speed = __constant_cpu_to_be32( + FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB| + FDMI_PORT_SPEED_4GB); else if (IS_QLA23XX(ha)) - eiter->a.sup_speed = __constant_cpu_to_be32(2); + eiter->a.sup_speed =__constant_cpu_to_be32( + FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB); else - eiter->a.sup_speed = __constant_cpu_to_be32(1); + eiter->a.sup_speed = __constant_cpu_to_be32( + FDMI_PORT_SPEED_1GB); size += 4 + 4; DEBUG13(printk("%s(%ld): SUPPORTED_SPEED=%x.\n", __func__, ha->host_no, @@ -1543,14 +1558,25 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) eiter->type = __constant_cpu_to_be16(FDMI_PORT_CURRENT_SPEED); eiter->len = __constant_cpu_to_be16(4 + 4); switch (ha->link_data_rate) { - case 0: - eiter->a.cur_speed = __constant_cpu_to_be32(1); + case PORT_SPEED_1GB: + eiter->a.cur_speed = + __constant_cpu_to_be32(FDMI_PORT_SPEED_1GB); + break; + case PORT_SPEED_2GB: + eiter->a.cur_speed = + __constant_cpu_to_be32(FDMI_PORT_SPEED_2GB); break; - case 1: - eiter->a.cur_speed = __constant_cpu_to_be32(2); + case PORT_SPEED_4GB: + eiter->a.cur_speed = + __constant_cpu_to_be32(FDMI_PORT_SPEED_4GB); break; - case 3: - eiter->a.cur_speed = __constant_cpu_to_be32(4); + case PORT_SPEED_8GB: + eiter->a.cur_speed = + __constant_cpu_to_be32(FDMI_PORT_SPEED_8GB); + break; + default: + eiter->a.cur_speed = + __constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN); break; } size += 4 + 4; @@ -1562,7 +1588,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE); eiter->len = __constant_cpu_to_be16(4 + 4); - max_frame_size = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? + max_frame_size = IS_FWI2_CAPABLE(ha) ? (uint32_t) icb24->frame_payload_size: (uint32_t) ha->init_cb->frame_payload_size; eiter->a.max_frame_size = cpu_to_be32(max_frame_size); @@ -1678,15 +1704,13 @@ qla2x00_gfpn_id(scsi_qla_host_t *ha, sw_info_t *list) struct ct_sns_req *ct_req; struct ct_sns_rsp *ct_rsp; - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + if (!IS_IIDMA_CAPABLE(ha)) return QLA_FUNCTION_FAILED; for (i = 0; i < MAX_FIBRE_DEVICES; i++) { /* Issue GFPN_ID */ - memset(list[i].fabric_port_name, 0, WWN_SIZE); - /* Prepare common MS IOCB */ - ms_pkt = ha->isp_ops.prep_ms_iocb(ha, GFPN_ID_REQ_SIZE, + ms_pkt = ha->isp_ops->prep_ms_iocb(ha, GFPN_ID_REQ_SIZE, GFPN_ID_RSP_SIZE); /* Prepare CT request */ @@ -1786,7 +1810,7 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list) struct ct_sns_req *ct_req; struct ct_sns_rsp *ct_rsp; - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + if (!IS_IIDMA_CAPABLE(ha)) return QLA_FUNCTION_FAILED; if (!ha->flags.gpsc_supported) return QLA_FUNCTION_FAILED; @@ -1797,8 +1821,6 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list) for (i = 0; i < MAX_FIBRE_DEVICES; i++) { /* Issue GFPN_ID */ - list[i].fp_speeds = list[i].fp_speed = 0; - /* Prepare common MS IOCB */ ms_pkt = qla24xx_prep_ms_fm_iocb(ha, GPSC_REQ_SIZE, GPSC_RSP_SIZE); @@ -1834,9 +1856,21 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list) } rval = QLA_FUNCTION_FAILED; } else { - /* Save portname */ - list[i].fp_speeds = ct_rsp->rsp.gpsc.speeds; - list[i].fp_speed = ct_rsp->rsp.gpsc.speed; + /* Save port-speed */ + switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) { + case BIT_15: + list[i].fp_speed = PORT_SPEED_1GB; + break; + case BIT_14: + list[i].fp_speed = PORT_SPEED_2GB; + break; + case BIT_13: + list[i].fp_speed = PORT_SPEED_4GB; + break; + case BIT_11: + list[i].fp_speed = PORT_SPEED_8GB; + break; + } DEBUG2_3(printk("scsi(%ld): GPSC ext entry - " "fpn %02x%02x%02x%02x%02x%02x%02x%02x speeds=%04x " @@ -1849,8 +1883,8 @@ qla2x00_gpsc(scsi_qla_host_t *ha, sw_info_t *list) list[i].fabric_port_name[5], list[i].fabric_port_name[6], list[i].fabric_port_name[7], - be16_to_cpu(list[i].fp_speeds), - be16_to_cpu(list[i].fp_speed))); + be16_to_cpu(ct_rsp->rsp.gpsc.speeds), + be16_to_cpu(ct_rsp->rsp.gpsc.speed))); } /* Last device exit. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index cc6ebb609e9..1a058ec9bd0 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -79,20 +79,20 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); - rval = ha->isp_ops.pci_config(ha); + rval = ha->isp_ops->pci_config(ha); if (rval) { DEBUG2(printk("scsi(%ld): Unable to configure PCI space.\n", ha->host_no)); return (rval); } - ha->isp_ops.reset_chip(ha); + ha->isp_ops->reset_chip(ha); - ha->isp_ops.get_flash_version(ha, ha->request_ring); + ha->isp_ops->get_flash_version(ha, ha->request_ring); qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); - ha->isp_ops.nvram_config(ha); + ha->isp_ops->nvram_config(ha); if (ha->flags.disable_serdes) { /* Mask HBA via NVRAM settings? */ @@ -108,7 +108,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { - rval = ha->isp_ops.chip_diag(ha); + rval = ha->isp_ops->chip_diag(ha); if (rval) return (rval); rval = qla2x00_setup_chip(ha); @@ -129,14 +129,13 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) int qla2100_pci_config(scsi_qla_host_t *ha) { - int ret; uint16_t w; uint32_t d; unsigned long flags; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); - ret = pci_set_mwi(ha->pdev); + pci_try_set_mwi(ha->pdev); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -164,7 +163,6 @@ qla2100_pci_config(scsi_qla_host_t *ha) int qla2300_pci_config(scsi_qla_host_t *ha) { - int ret; uint16_t w; uint32_t d; unsigned long flags = 0; @@ -172,7 +170,7 @@ qla2300_pci_config(scsi_qla_host_t *ha) struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); - ret = pci_set_mwi(ha->pdev); + pci_try_set_mwi(ha->pdev); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -250,15 +248,13 @@ qla2300_pci_config(scsi_qla_host_t *ha) int qla24xx_pci_config(scsi_qla_host_t *ha) { - int ret; uint16_t w; uint32_t d; unsigned long flags = 0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; - int pcix_cmd_reg, pcie_dctl_reg; pci_set_master(ha->pdev); - ret = pci_set_mwi(ha->pdev); + pci_try_set_mwi(ha->pdev); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); @@ -268,28 +264,12 @@ qla24xx_pci_config(scsi_qla_host_t *ha) pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); /* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */ - pcix_cmd_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX); - if (pcix_cmd_reg) { - uint16_t pcix_cmd; - - pcix_cmd_reg += PCI_X_CMD; - pci_read_config_word(ha->pdev, pcix_cmd_reg, &pcix_cmd); - pcix_cmd &= ~PCI_X_CMD_MAX_READ; - pcix_cmd |= 0x0008; - pci_write_config_word(ha->pdev, pcix_cmd_reg, pcix_cmd); - } + if (pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX)) + pcix_set_mmrbc(ha->pdev, 2048); /* PCIe -- adjust Maximum Read Request Size (2048). */ - pcie_dctl_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); - if (pcie_dctl_reg) { - uint16_t pcie_dctl; - - pcie_dctl_reg += PCI_EXP_DEVCTL; - pci_read_config_word(ha->pdev, pcie_dctl_reg, &pcie_dctl); - pcie_dctl &= ~PCI_EXP_DEVCTL_READRQ; - pcie_dctl |= 0x4000; - pci_write_config_word(ha->pdev, pcie_dctl_reg, pcie_dctl); - } + if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) + pcie_set_readrq(ha->pdev, 2048); /* Reset expansion ROM address decode enable */ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); @@ -307,6 +287,40 @@ qla24xx_pci_config(scsi_qla_host_t *ha) } /** + * qla25xx_pci_config() - Setup ISP25xx PCI configuration registers. + * @ha: HA context + * + * Returns 0 on success. + */ +int +qla25xx_pci_config(scsi_qla_host_t *ha) +{ + uint16_t w; + uint32_t d; + + pci_set_master(ha->pdev); + pci_try_set_mwi(ha->pdev); + + pci_read_config_word(ha->pdev, PCI_COMMAND, &w); + w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); + w &= ~PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(ha->pdev, PCI_COMMAND, w); + + /* PCIe -- adjust Maximum Read Request Size (2048). */ + if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) + pcie_set_readrq(ha->pdev, 2048); + + /* Reset expansion ROM address decode enable */ + pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); + d &= ~PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + + ha->chip_revision = ha->pdev->revision; + + return QLA_SUCCESS; +} + +/** * qla2x00_isp_firmware() - Choose firmware image. * @ha: HA context * @@ -351,7 +365,7 @@ qla2x00_reset_chip(scsi_qla_host_t *ha) uint32_t cnt; uint16_t cmd; - ha->isp_ops.disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); spin_lock_irqsave(&ha->hardware_lock, flags); @@ -551,7 +565,7 @@ qla24xx_reset_risc(scsi_qla_host_t *ha) void qla24xx_reset_chip(scsi_qla_host_t *ha) { - ha->isp_ops.disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); /* Perform RISC reset. */ qla24xx_reset_risc(ha); @@ -736,8 +750,10 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) fixed_size = offsetof(struct qla2300_fw_dump, data_ram); mem_size = (ha->fw_memory_size - 0x11000 + 1) * sizeof(uint16_t); - } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { - fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); + } else if (IS_FWI2_CAPABLE(ha)) { + fixed_size = IS_QLA25XX(ha) ? + offsetof(struct qla25xx_fw_dump, ext_mem): + offsetof(struct qla24xx_fw_dump, ext_mem); mem_size = (ha->fw_memory_size - 0x100000 + 1) * sizeof(uint32_t); @@ -879,7 +895,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) uint32_t srisc_address = 0; /* Load firmware sequences */ - rval = ha->isp_ops.load_risc(ha, &srisc_address); + rval = ha->isp_ops->load_risc(ha, &srisc_address); if (rval == QLA_SUCCESS) { DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC " "code.\n", ha->host_no)); @@ -1130,12 +1146,12 @@ qla2x00_init_rings(scsi_qla_host_t *ha) /* Initialize response queue entries */ qla2x00_init_response_q_entries(ha); - ha->isp_ops.config_rings(ha); + ha->isp_ops->config_rings(ha); spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Update any ISP specific firmware options before initialization. */ - ha->isp_ops.update_fw_options(ha); + ha->isp_ops->update_fw_options(ha); DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); @@ -1445,8 +1461,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) uint16_t cnt; uint8_t *dptr1, *dptr2; init_cb_t *icb = ha->init_cb; - nvram_t *nv = (nvram_t *)ha->request_ring; - uint8_t *ptr = (uint8_t *)ha->request_ring; + nvram_t *nv = ha->nvram; + uint8_t *ptr = ha->nvram; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; rval = QLA_SUCCESS; @@ -1459,13 +1475,12 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) ha->nvram_base = 0x80; /* Get NVRAM data and calculate checksum. */ - ha->isp_ops.read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size); + ha->isp_ops->read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size); for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++) chksum += *ptr++; DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); - DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, - ha->nvram_size)); + DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size)); /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || @@ -2064,17 +2079,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) } /* Base iIDMA settings on HBA port speed. */ - switch (ha->link_data_rate) { - case PORT_SPEED_1GB: - fcport->fp_speed = cpu_to_be16(BIT_15); - break; - case PORT_SPEED_2GB: - fcport->fp_speed = cpu_to_be16(BIT_14); - break; - case PORT_SPEED_4GB: - fcport->fp_speed = cpu_to_be16(BIT_13); - break; - } + fcport->fp_speed = ha->link_data_rate; qla2x00_update_fcport(ha, fcport); @@ -2115,38 +2120,25 @@ static void qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) { #define LS_UNKNOWN 2 - static char *link_speeds[5] = { "1", "2", "?", "4" }; + static char *link_speeds[5] = { "1", "2", "?", "4", "8" }; int rval; - uint16_t port_speed, mb[6]; + uint16_t mb[6]; - if (!IS_QLA24XX(ha)) + if (!IS_IIDMA_CAPABLE(ha)) return; - switch (be16_to_cpu(fcport->fp_speed)) { - case BIT_15: - port_speed = PORT_SPEED_1GB; - break; - case BIT_14: - port_speed = PORT_SPEED_2GB; - break; - case BIT_13: - port_speed = PORT_SPEED_4GB; - break; - default: + if (fcport->fp_speed == PORT_SPEED_UNKNOWN) { DEBUG2(printk("scsi(%ld): %02x%02x%02x%02x%02x%02x%02x%02x -- " - "unsupported FM port operating speed (%04x).\n", + "unsupported FM port operating speed.\n", ha->host_no, fcport->port_name[0], fcport->port_name[1], fcport->port_name[2], fcport->port_name[3], fcport->port_name[4], fcport->port_name[5], - fcport->port_name[6], fcport->port_name[7], - be16_to_cpu(fcport->fp_speed))); - port_speed = PORT_SPEED_UNKNOWN; - break; - } - if (port_speed == PORT_SPEED_UNKNOWN) + fcport->port_name[6], fcport->port_name[7])); return; + } - rval = qla2x00_set_idma_speed(ha, fcport->loop_id, port_speed, mb); + rval = qla2x00_set_idma_speed(ha, fcport->loop_id, fcport->fp_speed, + mb); if (rval != QLA_SUCCESS) { DEBUG2(printk("scsi(%ld): Unable to adjust iIDMA " "%02x%02x%02x%02x%02x%02x%02x%02x -- %04x %x %04x %04x.\n", @@ -2154,12 +2146,12 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) fcport->port_name[2], fcport->port_name[3], fcport->port_name[4], fcport->port_name[5], fcport->port_name[6], fcport->port_name[7], rval, - port_speed, mb[0], mb[1])); + fcport->fp_speed, mb[0], mb[1])); } else { DEBUG2(qla_printk(KERN_INFO, ha, "iIDMA adjusted to %s GB/s on " "%02x%02x%02x%02x%02x%02x%02x%02x.\n", - link_speeds[port_speed], fcport->port_name[0], + link_speeds[fcport->fp_speed], fcport->port_name[0], fcport->port_name[1], fcport->port_name[2], fcport->port_name[3], fcport->port_name[4], fcport->port_name[5], fcport->port_name[6], @@ -2267,7 +2259,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) scsi_qla_host_t *pha = to_qla_parent(ha); /* If FL port exists, then SNS is present */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) loop_id = NPH_F_PORT; else loop_id = SNS_FL_PORT; @@ -2294,11 +2286,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) qla2x00_fdmi_register(ha); /* Ensure we are logged into the SNS. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) loop_id = NPH_SNS; else loop_id = SIMPLE_NAME_SERVER; - ha->isp_ops.fabric_login(ha, loop_id, 0xff, 0xff, + ha->isp_ops->fabric_login(ha, loop_id, 0xff, 0xff, 0xfc, mb, BIT_1 | BIT_0); if (mb[0] != MBS_COMMAND_COMPLETE) { DEBUG2(qla_printk(KERN_INFO, ha, @@ -2355,7 +2347,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) (fcport->flags & FCF_TAPE_PRESENT) == 0 && fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_BROADCAST) { - ha->isp_ops.fabric_logout(ha, + ha->isp_ops->fabric_logout(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, @@ -2664,7 +2656,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) (fcport->flags & FCF_TAPE_PRESENT) == 0 && fcport->port_type != FCT_INITIATOR && fcport->port_type != FCT_BROADCAST) { - ha->isp_ops.fabric_logout(ha, fcport->loop_id, + ha->isp_ops->fabric_logout(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); fcport->loop_id = FC_NO_LOOP_ID; @@ -2919,7 +2911,7 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport, opts |= BIT_1; rval = qla2x00_get_port_database(ha, fcport, opts); if (rval != QLA_SUCCESS) { - ha->isp_ops.fabric_logout(ha, fcport->loop_id, + ha->isp_ops->fabric_logout(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); qla2x00_mark_device_lost(ha, fcport, 1, 0); @@ -2964,7 +2956,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, fcport->d_id.b.area, fcport->d_id.b.al_pa)); /* Login fcport on switch. */ - ha->isp_ops.fabric_login(ha, fcport->loop_id, + ha->isp_ops->fabric_login(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, mb, BIT_0); if (mb[0] == MBS_PORT_ID_USED) { @@ -3032,7 +3024,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, * dead. */ *next_loopid = fcport->loop_id; - ha->isp_ops.fabric_logout(ha, fcport->loop_id, + ha->isp_ops->fabric_logout(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); qla2x00_mark_device_lost(ha, fcport, 1, 0); @@ -3050,7 +3042,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport, fcport->d_id.b.al_pa, fcport->loop_id, jiffies)); *next_loopid = fcport->loop_id; - ha->isp_ops.fabric_logout(ha, fcport->loop_id, + ha->isp_ops->fabric_logout(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa); fcport->loop_id = FC_NO_LOOP_ID; @@ -3206,7 +3198,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Performing ISP error recovery - ha= %p.\n", ha); - ha->isp_ops.reset_chip(ha); + ha->isp_ops->reset_chip(ha); atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); if (atomic_read(&ha->loop_state) != LOOP_DOWN) { @@ -3232,9 +3224,9 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) } spin_unlock_irqrestore(&ha->hardware_lock, flags); - ha->isp_ops.get_flash_version(ha, ha->request_ring); + ha->isp_ops->get_flash_version(ha, ha->request_ring); - ha->isp_ops.nvram_config(ha); + ha->isp_ops->nvram_config(ha); if (!qla2x00_restart_isp(ha)) { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); @@ -3249,7 +3241,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ha->flags.online = 1; - ha->isp_ops.enable_intrs(ha); + ha->isp_ops->enable_intrs(ha); ha->isp_abort_cnt = 0; clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); @@ -3274,7 +3266,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) * The next call disables the board * completely. */ - ha->isp_ops.reset_adapter(ha); + ha->isp_ops->reset_adapter(ha); ha->flags.online = 0; clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); @@ -3331,7 +3323,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) /* If firmware needs to be loaded */ if (qla2x00_isp_firmware(ha)) { ha->flags.online = 0; - if (!(status = ha->isp_ops.chip_diag(ha))) { + if (!(status = ha->isp_ops->chip_diag(ha))) { if (IS_QLA2100(ha) || IS_QLA2200(ha)) { status = qla2x00_setup_chip(ha); goto done; @@ -3339,7 +3331,8 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) { + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha) && + !IS_QLA25XX(ha)) { /* * Disable SRAM, Instruction RAM and GP RAM * parity. @@ -3355,7 +3348,8 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) spin_lock_irqsave(&ha->hardware_lock, flags); - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) { + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha) && + !IS_QLA25XX(ha)) { /* Enable proper parity */ if (IS_QLA2300(ha)) /* SRAM parity */ @@ -3423,7 +3417,7 @@ qla2x00_reset_adapter(scsi_qla_host_t *ha) struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; ha->flags.online = 0; - ha->isp_ops.disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); spin_lock_irqsave(&ha->hardware_lock, flags); WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); @@ -3440,7 +3434,7 @@ qla24xx_reset_adapter(scsi_qla_host_t *ha) struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; ha->flags.online = 0; - ha->isp_ops.disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); spin_lock_irqsave(&ha->hardware_lock, flags); WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET); @@ -3484,7 +3478,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) rval = QLA_SUCCESS; icb = (struct init_cb_24xx *)ha->init_cb; - nv = (struct nvram_24xx *)ha->request_ring; + nv = ha->nvram; /* Determine NVRAM starting address. */ ha->nvram_size = sizeof(struct nvram_24xx); @@ -3496,16 +3490,20 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) ha->vpd_base = FA_NVRAM_VPD1_ADDR; } - /* Get NVRAM data and calculate checksum. */ + /* Get VPD data into cache */ + ha->vpd = ha->nvram + VPD_OFFSET; + ha->isp_ops->read_nvram(ha, (uint8_t *)ha->vpd, + ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4); + + /* Get NVRAM data into cache and calculate checksum. */ dptr = (uint32_t *)nv; - ha->isp_ops.read_nvram(ha, (uint8_t *)dptr, ha->nvram_base, + ha->isp_ops->read_nvram(ha, (uint8_t *)dptr, ha->nvram_base, ha->nvram_size); for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++) chksum += le32_to_cpu(*dptr++); DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); - DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, - ha->nvram_size)); + DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size)); /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' @@ -4012,7 +4010,7 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) { int ret, retries; - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + if (!IS_FWI2_CAPABLE(ha)) return; if (!ha->fw_major_version) return; diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index d3023338628..8e3b04464cf 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -104,7 +104,7 @@ static __inline__ void qla2x00_poll(scsi_qla_host_t *); static inline void qla2x00_poll(scsi_qla_host_t *ha) { - ha->isp_ops.intr_handler(0, ha); + ha->isp_ops->intr_handler(0, ha); } static __inline__ void qla2x00_check_fabric_devices(scsi_qla_host_t *); @@ -163,7 +163,7 @@ static inline int qla2x00_is_reserved_id(scsi_qla_host_t *, uint16_t); static inline int qla2x00_is_reserved_id(scsi_qla_host_t *ha, uint16_t loop_id) { - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) return (loop_id > NPH_LAST_HANDLE); return ((loop_id > ha->last_loop_id && loop_id < SNS_FIRST_LOOP_ID) || diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index c71863ff548..3a5e78cb6b3 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -326,7 +326,7 @@ qla2x00_start_scsi(srb_t *sp) tot_dsds = nseg; /* Calculate the number of request entries needed. */ - req_cnt = ha->isp_ops.calc_req_entries(tot_dsds); + req_cnt = ha->isp_ops->calc_req_entries(tot_dsds); if (ha->req_q_cnt < (req_cnt + 2)) { cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg)); if (ha->req_ring_index < cnt) @@ -364,7 +364,7 @@ qla2x00_start_scsi(srb_t *sp) cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); /* Build IOCB segments */ - ha->isp_ops.build_iocbs(sp, cmd_pkt, tot_dsds); + ha->isp_ops->build_iocbs(sp, cmd_pkt, tot_dsds); /* Set total data segment count. */ cmd_pkt->entry_count = (uint8_t)req_cnt; @@ -432,7 +432,7 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, mrk->entry_type = MARKER_TYPE; mrk->modifier = type; if (type != MK_SYNC_ALL) { - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle = cpu_to_le16(loop_id); mrk24->lun[1] = LSB(lun); @@ -487,7 +487,7 @@ qla2x00_req_pkt(scsi_qla_host_t *ha) for (timer = HZ; timer; timer--) { if ((req_cnt + 2) >= ha->req_q_cnt) { /* Calculate number of free request entries. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) cnt = (uint16_t)RD_REG_DWORD( ®->isp24.req_q_out); else @@ -561,7 +561,7 @@ qla2x00_isp_cmd(scsi_qla_host_t *ha) ha->request_ring_ptr++; /* Set chip new ring index. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { WRT_REG_DWORD(®->isp24.req_q_in, ha->req_ring_index); RD_REG_DWORD_RELAXED(®->isp24.req_q_in); } else { diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 0ba4c8d3787..eecae9905ec 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -143,7 +143,7 @@ qla2300_intr_handler(int irq, void *dev_id) WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); RD_REG_WORD(®->hccr); - ha->isp_ops.fw_dump(ha, 1); + ha->isp_ops->fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; } else if ((stat & HSR_RISC_INT) == 0) @@ -247,7 +247,7 @@ void qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) { #define LS_UNKNOWN 2 - static char *link_speeds[5] = { "1", "2", "?", "4", "10" }; + static char *link_speeds[5] = { "1", "2", "?", "4", "8" }; char *link_speed; uint16_t handle_cnt; uint16_t cnt; @@ -334,9 +334,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n", mb[1], mb[2], mb[3]); - ha->isp_ops.fw_dump(ha, 1); + ha->isp_ops->fw_dump(ha, 1); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { if (mb[1] == 0 && mb[2] == 0) { qla_printk(KERN_ERR, ha, "Unrecoverable Hardware Error: adapter " @@ -490,6 +490,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); ha->flags.gpsc_supported = 1; + ha->flags.management_server_logged_in = 0; break; case MBA_CHG_IN_CONNECTION: /* Change in connection mode */ @@ -601,7 +602,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) "scsi(%ld): [R|Z]IO update completion.\n", ha->host_no)); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) qla24xx_process_response_queue(ha); else qla2x00_process_response_queue(ha); @@ -823,7 +824,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) sts = (sts_entry_t *) pkt; sts24 = (struct sts_entry_24xx *) pkt; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { comp_status = le16_to_cpu(sts24->comp_status); scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK; } else { @@ -872,7 +873,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) fcport = sp->fcport; sense_len = rsp_info_len = resid_len = fw_resid_len = 0; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { sense_len = le32_to_cpu(sts24->sense_len); rsp_info_len = le32_to_cpu(sts24->rsp_data_len); resid_len = le32_to_cpu(sts24->rsp_residual_count); @@ -891,7 +892,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) /* Check for any FCP transport errors. */ if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { /* Sense data lies beyond any FCP RESPONSE data. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) sense_data += rsp_info_len; if (rsp_info_len > 3 && rsp_info[3]) { DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " @@ -990,7 +991,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) case CS_DATA_UNDERRUN: resid = resid_len; /* Use F/W calculated residual length. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) resid = fw_resid_len; if (scsi_status & SS_RESIDUAL_UNDER) { @@ -1062,6 +1063,25 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) cp->device->id, cp->device->lun, cp, cp->serial_number)); + /* + * In case of a Underrun condition, set both the lscsi + * status and the completion status to appropriate + * values. + */ + if (resid && + ((unsigned)(scsi_bufflen(cp) - resid) < + cp->underflow)) { + DEBUG2(qla_printk(KERN_INFO, ha, + "scsi(%ld:%d:%d:%d): Mid-layer underflow " + "detected (%x of %x bytes)...returning " + "error status.\n", ha->host_no, + cp->device->channel, cp->device->id, + cp->device->lun, resid, + scsi_bufflen(cp))); + + cp->result = DID_ERROR << 16 | lscsi_status; + } + if (sense_len) DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, CMD_ACTUAL_SNSLEN(cp))); @@ -1166,7 +1186,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) case CS_TIMEOUT: cp->result = DID_BUS_BUSY << 16; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d:%d): TIMEOUT status detected " "0x%x-0x%x\n", ha->host_no, cp->device->channel, @@ -1235,7 +1255,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt) } /* Move sense data. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) host_to_fcp_swap(pkt->data, sizeof(pkt->data)); memcpy(sp->request_sense_ptr, pkt->data, sense_sz); DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); @@ -1483,7 +1503,7 @@ qla24xx_intr_handler(int irq, void *dev_id) qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " "Dumping firmware!\n", hccr); - ha->isp_ops.fw_dump(ha, 1); + ha->isp_ops->fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; } else if ((stat & HSRX_RISC_INT) == 0) @@ -1617,7 +1637,7 @@ qla24xx_msix_default(int irq, void *dev_id) qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " "Dumping firmware!\n", hccr); - ha->isp_ops.fw_dump(ha, 1); + ha->isp_ops->fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; } else if ((stat & HSRX_RISC_INT) == 0) @@ -1739,11 +1759,11 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) int ret; /* If possible, enable MSI-X. */ - if (!IS_QLA2432(ha)) + if (!IS_QLA2432(ha) && !IS_QLA2532(ha)) goto skip_msix; - if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX || - !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) { + if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX || + !QLA_MSIX_FW_MODE_1(ha->fw_attributes))) { DEBUG2(qla_printk(KERN_WARNING, ha, "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n", ha->chip_revision, ha->fw_attributes)); @@ -1762,7 +1782,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha) "MSI-X: Falling back-to INTa mode -- %d.\n", ret); skip_msix: - if (!IS_QLA24XX(ha)) + if (!IS_QLA24XX(ha) && !IS_QLA2532(ha)) goto skip_msi; ret = pci_enable_msi(ha->pdev); @@ -1772,7 +1792,7 @@ skip_msix: } skip_msi: - ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler, + ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler, IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha); if (!ret) { ha->flags.inta_enabled = 1; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 2cd0cff2592..d3746ec80a8 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -90,7 +90,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) spin_lock_irqsave(&ha->hardware_lock, flags); /* Load mailbox registers. */ - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) optr = (uint16_t __iomem *)®->isp24.mailbox0; else optr = (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 0); @@ -154,7 +154,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); else WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); @@ -175,7 +175,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) DEBUG3_11(printk("%s(%ld): cmd=%x POLLING MODE.\n", __func__, ha->host_no, command)); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT); else WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT); @@ -228,7 +228,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) uint16_t mb0; uint32_t ictrl; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mb0 = RD_REG_WORD(®->isp24.mailbox0); ictrl = RD_REG_DWORD(®->isp24.ictrl); } else { @@ -322,7 +322,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (MSW(risc_addr) || IS_FWI2_CAPABLE(ha)) { mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED; mcp->mb[8] = MSW(risc_addr); mcp->out_mb = MBX_8|MBX_0; @@ -336,7 +336,7 @@ qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr, mcp->mb[6] = MSW(MSD(req_dma)); mcp->mb[7] = LSW(MSD(req_dma)); mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mcp->mb[4] = MSW(risc_code_size); mcp->mb[5] = LSW(risc_code_size); mcp->out_mb |= MBX_5|MBX_4; @@ -387,7 +387,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) mcp->mb[0] = MBC_EXECUTE_FIRMWARE; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->mb[3] = 0; @@ -410,7 +410,7 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, ha->host_no, rval, mcp->mb[0])); } else { - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { DEBUG11(printk("%s(%ld): done exchanges=%x.\n", __func__, ha->host_no, mcp->mb[1])); } else { @@ -551,7 +551,7 @@ qla2x00_set_fw_options(scsi_qla_host_t *ha, uint16_t *fwopts) mcp->mb[3] = fwopts[3]; mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mcp->in_mb |= MBX_1; } else { mcp->mb[10] = fwopts[10]; @@ -664,7 +664,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) mcp->mb[0] = MBC_VERIFY_CHECKSUM; mcp->out_mb = MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->out_mb |= MBX_2|MBX_1; @@ -681,8 +681,8 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr) if (rval != QLA_SUCCESS) { DEBUG2_3_11(printk("%s(%ld): failed=%x chk sum=%x.\n", __func__, - ha->host_no, rval, (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? - (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1]))); + ha->host_no, rval, IS_FWI2_CAPABLE(ha) ? + (mcp->mb[2] << 16) | mcp->mb[1]: mcp->mb[1])); } else { DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); } @@ -739,7 +739,7 @@ qla2x00_issue_iocb(scsi_qla_host_t *ha, void* buffer, dma_addr_t phys_addr, /* Mask reserved bits. */ sts_entry->entry_status &= - IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RF_MASK_24XX :RF_MASK; + IS_FWI2_CAPABLE(ha) ? RF_MASK_24XX :RF_MASK; } return rval; @@ -1085,7 +1085,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) memset(pd, 0, max(PORT_DATABASE_SIZE, PORT_DATABASE_24XX_SIZE)); mcp->mb[0] = MBC_GET_PORT_DATABASE; - if (opt != 0 && !IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + if (opt != 0 && !IS_FWI2_CAPABLE(ha)) mcp->mb[0] = MBC_ENHANCED_GET_PORT_DATABASE; mcp->mb[2] = MSW(pd_dma); mcp->mb[3] = LSW(pd_dma); @@ -1094,7 +1094,7 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) mcp->mb[9] = ha->vp_idx; mcp->out_mb = MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mcp->mb[1] = fcport->loop_id; mcp->mb[10] = opt; mcp->out_mb |= MBX_10|MBX_1; @@ -1107,15 +1107,15 @@ qla2x00_get_port_database(scsi_qla_host_t *ha, fc_port_t *fcport, uint8_t opt) mcp->mb[1] = fcport->loop_id << 8 | opt; mcp->out_mb |= MBX_1; } - mcp->buf_size = (IS_QLA24XX(ha) || IS_QLA54XX(ha) ? - PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE); + mcp->buf_size = IS_FWI2_CAPABLE(ha) ? + PORT_DATABASE_24XX_SIZE : PORT_DATABASE_SIZE; mcp->flags = MBX_DMA_IN; mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); rval = qla2x00_mailbox_command(ha, mcp); if (rval != QLA_SUCCESS) goto gpd_error_out; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { pd24 = (struct port_database_24xx *) pd; /* Check for logged in state. */ @@ -1333,7 +1333,7 @@ qla2x00_lip_reset(scsi_qla_host_t *ha) DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mcp->mb[0] = MBC_LIP_FULL_LOGIN; mcp->mb[1] = BIT_6; mcp->mb[2] = 0; @@ -1637,7 +1637,7 @@ qla2x00_login_local_device(scsi_qla_host_t *ha, fc_port_t *fcport, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) + if (IS_FWI2_CAPABLE(ha)) return qla24xx_login_fabric(ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa, mb_ret, opt); @@ -1821,7 +1821,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *ha) ha->host_no)); mcp->mb[0] = MBC_LIP_FULL_LOGIN; - mcp->mb[1] = IS_QLA24XX(ha) || IS_QLA54XX(ha) ? BIT_3: 0; + mcp->mb[1] = IS_FWI2_CAPABLE(ha) ? BIT_3: 0; mcp->mb[2] = 0; mcp->mb[3] = 0; mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; @@ -1871,7 +1871,7 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, mcp->mb[0] = MBC_GET_ID_LIST; mcp->out_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mcp->mb[2] = MSW(id_list_dma); mcp->mb[3] = LSW(id_list_dma); mcp->mb[6] = MSW(MSD(id_list_dma)); @@ -2063,7 +2063,7 @@ qla2x00_get_link_status(scsi_qla_host_t *ha, uint16_t loop_id, mcp->mb[7] = LSW(MSD(stat_buf_dma)); mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0; mcp->in_mb = MBX_0; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { mcp->mb[1] = loop_id; mcp->mb[4] = 0; mcp->mb[10] = 0; @@ -2334,7 +2334,7 @@ qla2x00_system_error(scsi_qla_host_t *ha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + if (!IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); @@ -2444,7 +2444,7 @@ qla2x00_stop_firmware(scsi_qla_host_t *ha) mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + if (!IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); @@ -2474,7 +2474,7 @@ qla2x00_trace_control(scsi_qla_host_t *ha, uint16_t ctrl, dma_addr_t eft_dma, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + if (!IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); @@ -2514,7 +2514,7 @@ qla2x00_read_sfp(scsi_qla_host_t *ha, dma_addr_t sfp_dma, uint16_t addr, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + if (!IS_FWI2_CAPABLE(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); @@ -2552,7 +2552,7 @@ qla2x00_get_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha)) + if (!IS_IIDMA_CAPABLE(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); @@ -2595,7 +2595,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *ha, uint16_t loop_id, mbx_cmd_t mc; mbx_cmd_t *mcp = &mc; - if (!IS_QLA24XX(ha)) + if (!IS_IIDMA_CAPABLE(ha)) return QLA_FUNCTION_FAILED; DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index b5a77b0c0de..acca898ce0a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -265,6 +265,8 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str) strcpy(str, "PCIe ("); if (lspeed == 1) strcat(str, "2.5Gb/s "); + else if (lspeed == 2) + strcat(str, "5.0Gb/s "); else strcat(str, "<unknown> "); snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth); @@ -343,6 +345,12 @@ qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str) strcat(str, "[IP] "); if (ha->fw_attributes & BIT_2) strcat(str, "[Multi-ID] "); + if (ha->fw_attributes & BIT_3) + strcat(str, "[SB-2] "); + if (ha->fw_attributes & BIT_4) + strcat(str, "[T10 CRC] "); + if (ha->fw_attributes & BIT_5) + strcat(str, "[VI] "); if (ha->fw_attributes & BIT_13) strcat(str, "[Experimental]"); return str; @@ -681,7 +689,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) DEBUG3(qla2x00_print_scsi_cmd(cmd)); spin_unlock_irqrestore(&pha->hardware_lock, flags); - if (ha->isp_ops.abort_command(ha, sp)) { + if (ha->isp_ops->abort_command(ha, sp)) { DEBUG2(printk("%s(%ld): abort_command " "mbx failed.\n", __func__, ha->host_no)); } else { @@ -813,7 +821,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) #if defined(LOGOUT_AFTER_DEVICE_RESET) if (ret == SUCCESS) { if (fcport->flags & FC_FABRIC_DEVICE) { - ha->isp_ops.fabric_logout(ha, fcport->loop_id); + ha->isp_ops->fabric_logout(ha, fcport->loop_id); qla2x00_mark_device_lost(ha, fcport, 0, 0); } } @@ -1105,7 +1113,7 @@ static int qla2x00_device_reset(scsi_qla_host_t *ha, fc_port_t *reset_fcport) { /* Abort Target command will clear Reservation */ - return ha->isp_ops.abort_target(reset_fcport); + return ha->isp_ops->abort_target(reset_fcport); } static int @@ -1184,8 +1192,8 @@ qla2x00_config_dma_addressing(scsi_qla_host_t *ha) !pci_set_consistent_dma_mask(ha->pdev, DMA_64BIT_MASK)) { /* Ok, a 64bit DMA mask is applicable. */ ha->flags.enable_64bit_addressing = 1; - ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_64; - ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_64; + ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64; + ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64; return; } } @@ -1194,6 +1202,193 @@ qla2x00_config_dma_addressing(scsi_qla_host_t *ha) pci_set_consistent_dma_mask(ha->pdev, DMA_32BIT_MASK); } +static void +qla2x00_enable_intrs(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + spin_lock_irqsave(&ha->hardware_lock, flags); + ha->interrupts_on = 1; + /* enable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, ICR_EN_INT | ICR_EN_RISC); + RD_REG_WORD(®->ictrl); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + +} + +static void +qla2x00_disable_intrs(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + + spin_lock_irqsave(&ha->hardware_lock, flags); + ha->interrupts_on = 0; + /* disable risc and host interrupts */ + WRT_REG_WORD(®->ictrl, 0); + RD_REG_WORD(®->ictrl); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +static void +qla24xx_enable_intrs(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + spin_lock_irqsave(&ha->hardware_lock, flags); + ha->interrupts_on = 1; + WRT_REG_DWORD(®->ictrl, ICRX_EN_RISC_INT); + RD_REG_DWORD(®->ictrl); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +static void +qla24xx_disable_intrs(scsi_qla_host_t *ha) +{ + unsigned long flags = 0; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + spin_lock_irqsave(&ha->hardware_lock, flags); + ha->interrupts_on = 0; + WRT_REG_DWORD(®->ictrl, 0); + RD_REG_DWORD(®->ictrl); + spin_unlock_irqrestore(&ha->hardware_lock, flags); +} + +static struct isp_operations qla2100_isp_ops = { + .pci_config = qla2100_pci_config, + .reset_chip = qla2x00_reset_chip, + .chip_diag = qla2x00_chip_diag, + .config_rings = qla2x00_config_rings, + .reset_adapter = qla2x00_reset_adapter, + .nvram_config = qla2x00_nvram_config, + .update_fw_options = qla2x00_update_fw_options, + .load_risc = qla2x00_load_risc, + .pci_info_str = qla2x00_pci_info_str, + .fw_version_str = qla2x00_fw_version_str, + .intr_handler = qla2100_intr_handler, + .enable_intrs = qla2x00_enable_intrs, + .disable_intrs = qla2x00_disable_intrs, + .abort_command = qla2x00_abort_command, + .abort_target = qla2x00_abort_target, + .fabric_login = qla2x00_login_fabric, + .fabric_logout = qla2x00_fabric_logout, + .calc_req_entries = qla2x00_calc_iocbs_32, + .build_iocbs = qla2x00_build_scsi_iocbs_32, + .prep_ms_iocb = qla2x00_prep_ms_iocb, + .prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb, + .read_nvram = qla2x00_read_nvram_data, + .write_nvram = qla2x00_write_nvram_data, + .fw_dump = qla2100_fw_dump, + .beacon_on = NULL, + .beacon_off = NULL, + .beacon_blink = NULL, + .read_optrom = qla2x00_read_optrom_data, + .write_optrom = qla2x00_write_optrom_data, + .get_flash_version = qla2x00_get_flash_version, +}; + +static struct isp_operations qla2300_isp_ops = { + .pci_config = qla2300_pci_config, + .reset_chip = qla2x00_reset_chip, + .chip_diag = qla2x00_chip_diag, + .config_rings = qla2x00_config_rings, + .reset_adapter = qla2x00_reset_adapter, + .nvram_config = qla2x00_nvram_config, + .update_fw_options = qla2x00_update_fw_options, + .load_risc = qla2x00_load_risc, + .pci_info_str = qla2x00_pci_info_str, + .fw_version_str = qla2x00_fw_version_str, + .intr_handler = qla2300_intr_handler, + .enable_intrs = qla2x00_enable_intrs, + .disable_intrs = qla2x00_disable_intrs, + .abort_command = qla2x00_abort_command, + .abort_target = qla2x00_abort_target, + .fabric_login = qla2x00_login_fabric, + .fabric_logout = qla2x00_fabric_logout, + .calc_req_entries = qla2x00_calc_iocbs_32, + .build_iocbs = qla2x00_build_scsi_iocbs_32, + .prep_ms_iocb = qla2x00_prep_ms_iocb, + .prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb, + .read_nvram = qla2x00_read_nvram_data, + .write_nvram = qla2x00_write_nvram_data, + .fw_dump = qla2300_fw_dump, + .beacon_on = qla2x00_beacon_on, + .beacon_off = qla2x00_beacon_off, + .beacon_blink = qla2x00_beacon_blink, + .read_optrom = qla2x00_read_optrom_data, + .write_optrom = qla2x00_write_optrom_data, + .get_flash_version = qla2x00_get_flash_version, +}; + +static struct isp_operations qla24xx_isp_ops = { + .pci_config = qla24xx_pci_config, + .reset_chip = qla24xx_reset_chip, + .chip_diag = qla24xx_chip_diag, + .config_rings = qla24xx_config_rings, + .reset_adapter = qla24xx_reset_adapter, + .nvram_config = qla24xx_nvram_config, + .update_fw_options = qla24xx_update_fw_options, + .load_risc = qla24xx_load_risc, + .pci_info_str = qla24xx_pci_info_str, + .fw_version_str = qla24xx_fw_version_str, + .intr_handler = qla24xx_intr_handler, + .enable_intrs = qla24xx_enable_intrs, + .disable_intrs = qla24xx_disable_intrs, + .abort_command = qla24xx_abort_command, + .abort_target = qla24xx_abort_target, + .fabric_login = qla24xx_login_fabric, + .fabric_logout = qla24xx_fabric_logout, + .calc_req_entries = NULL, + .build_iocbs = NULL, + .prep_ms_iocb = qla24xx_prep_ms_iocb, + .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, + .read_nvram = qla24xx_read_nvram_data, + .write_nvram = qla24xx_write_nvram_data, + .fw_dump = qla24xx_fw_dump, + .beacon_on = qla24xx_beacon_on, + .beacon_off = qla24xx_beacon_off, + .beacon_blink = qla24xx_beacon_blink, + .read_optrom = qla24xx_read_optrom_data, + .write_optrom = qla24xx_write_optrom_data, + .get_flash_version = qla24xx_get_flash_version, +}; + +static struct isp_operations qla25xx_isp_ops = { + .pci_config = qla25xx_pci_config, + .reset_chip = qla24xx_reset_chip, + .chip_diag = qla24xx_chip_diag, + .config_rings = qla24xx_config_rings, + .reset_adapter = qla24xx_reset_adapter, + .nvram_config = qla24xx_nvram_config, + .update_fw_options = qla24xx_update_fw_options, + .load_risc = qla24xx_load_risc, + .pci_info_str = qla24xx_pci_info_str, + .fw_version_str = qla24xx_fw_version_str, + .intr_handler = qla24xx_intr_handler, + .enable_intrs = qla24xx_enable_intrs, + .disable_intrs = qla24xx_disable_intrs, + .abort_command = qla24xx_abort_command, + .abort_target = qla24xx_abort_target, + .fabric_login = qla24xx_login_fabric, + .fabric_logout = qla24xx_fabric_logout, + .calc_req_entries = NULL, + .build_iocbs = NULL, + .prep_ms_iocb = qla24xx_prep_ms_iocb, + .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, + .read_nvram = qla25xx_read_nvram_data, + .write_nvram = qla25xx_write_nvram_data, + .fw_dump = qla25xx_fw_dump, + .beacon_on = qla24xx_beacon_on, + .beacon_off = qla24xx_beacon_off, + .beacon_blink = qla24xx_beacon_blink, + .read_optrom = qla24xx_read_optrom_data, + .write_optrom = qla24xx_write_optrom_data, + .get_flash_version = qla24xx_get_flash_version, +}; + static inline void qla2x00_set_isp_flags(scsi_qla_host_t *ha) { @@ -1238,19 +1433,32 @@ qla2x00_set_isp_flags(scsi_qla_host_t *ha) case PCI_DEVICE_ID_QLOGIC_ISP2422: ha->device_type |= DT_ISP2422; ha->device_type |= DT_ZIO_SUPPORTED; + ha->device_type |= DT_FWI2; + ha->device_type |= DT_IIDMA; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP2432: ha->device_type |= DT_ISP2432; ha->device_type |= DT_ZIO_SUPPORTED; + ha->device_type |= DT_FWI2; + ha->device_type |= DT_IIDMA; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP5422: ha->device_type |= DT_ISP5422; + ha->device_type |= DT_FWI2; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; case PCI_DEVICE_ID_QLOGIC_ISP5432: ha->device_type |= DT_ISP5432; + ha->device_type |= DT_FWI2; + ha->fw_srisc_address = RISC_START_ADDRESS_2400; + break; + case PCI_DEVICE_ID_QLOGIC_ISP2532: + ha->device_type |= DT_ISP2532; + ha->device_type |= DT_ZIO_SUPPORTED; + ha->device_type |= DT_FWI2; + ha->device_type |= DT_IIDMA; ha->fw_srisc_address = RISC_START_ADDRESS_2400; break; } @@ -1323,61 +1531,6 @@ iospace_error_exit: } static void -qla2x00_enable_intrs(scsi_qla_host_t *ha) -{ - unsigned long flags = 0; - struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->interrupts_on = 1; - /* enable risc and host interrupts */ - WRT_REG_WORD(®->ictrl, ICR_EN_INT | ICR_EN_RISC); - RD_REG_WORD(®->ictrl); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - -} - -static void -qla2x00_disable_intrs(scsi_qla_host_t *ha) -{ - unsigned long flags = 0; - struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; - - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->interrupts_on = 0; - /* disable risc and host interrupts */ - WRT_REG_WORD(®->ictrl, 0); - RD_REG_WORD(®->ictrl); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - -static void -qla24xx_enable_intrs(scsi_qla_host_t *ha) -{ - unsigned long flags = 0; - struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; - - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->interrupts_on = 1; - WRT_REG_DWORD(®->ictrl, ICRX_EN_RISC_INT); - RD_REG_DWORD(®->ictrl); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - -static void -qla24xx_disable_intrs(scsi_qla_host_t *ha) -{ - unsigned long flags = 0; - struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; - - spin_lock_irqsave(&ha->hardware_lock, flags); - ha->interrupts_on = 0; - WRT_REG_DWORD(®->ictrl, 0); - RD_REG_DWORD(®->ictrl); - spin_unlock_irqrestore(&ha->hardware_lock, flags); -} - -static void qla2xxx_scan_start(struct Scsi_Host *shost) { scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; @@ -1411,7 +1564,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) struct Scsi_Host *host; scsi_qla_host_t *ha; unsigned long flags = 0; - char pci_info[20]; + char pci_info[30]; char fw_str[30]; struct scsi_host_template *sht; @@ -1422,7 +1575,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 || - pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432) + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 || + pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) sht = &qla24xx_driver_template; host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t)); if (host == NULL) { @@ -1466,33 +1620,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->max_q_depth = ql2xmaxqdepth; /* Assign ISP specific operations. */ - ha->isp_ops.pci_config = qla2100_pci_config; - ha->isp_ops.reset_chip = qla2x00_reset_chip; - ha->isp_ops.chip_diag = qla2x00_chip_diag; - ha->isp_ops.config_rings = qla2x00_config_rings; - ha->isp_ops.reset_adapter = qla2x00_reset_adapter; - ha->isp_ops.nvram_config = qla2x00_nvram_config; - ha->isp_ops.update_fw_options = qla2x00_update_fw_options; - ha->isp_ops.load_risc = qla2x00_load_risc; - ha->isp_ops.pci_info_str = qla2x00_pci_info_str; - ha->isp_ops.fw_version_str = qla2x00_fw_version_str; - ha->isp_ops.intr_handler = qla2100_intr_handler; - ha->isp_ops.enable_intrs = qla2x00_enable_intrs; - ha->isp_ops.disable_intrs = qla2x00_disable_intrs; - ha->isp_ops.abort_command = qla2x00_abort_command; - ha->isp_ops.abort_target = qla2x00_abort_target; - ha->isp_ops.fabric_login = qla2x00_login_fabric; - ha->isp_ops.fabric_logout = qla2x00_fabric_logout; - ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32; - ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32; - ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb; - ha->isp_ops.prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb; - ha->isp_ops.read_nvram = qla2x00_read_nvram_data; - ha->isp_ops.write_nvram = qla2x00_write_nvram_data; - ha->isp_ops.fw_dump = qla2100_fw_dump; - ha->isp_ops.read_optrom = qla2x00_read_optrom_data; - ha->isp_ops.write_optrom = qla2x00_write_optrom_data; - ha->isp_ops.get_flash_version = qla2x00_get_flash_version; if (IS_QLA2100(ha)) { host->max_id = MAX_TARGETS_2100; ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; @@ -1501,6 +1628,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->last_loop_id = SNS_LAST_LOOP_ID_2100; host->sg_tablesize = 32; ha->gid_list_info_size = 4; + ha->isp_ops = &qla2100_isp_ops; } else if (IS_QLA2200(ha)) { host->max_id = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; @@ -1508,21 +1636,17 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->response_q_length = RESPONSE_ENTRY_CNT_2100; ha->last_loop_id = SNS_LAST_LOOP_ID_2100; ha->gid_list_info_size = 4; + ha->isp_ops = &qla2100_isp_ops; } else if (IS_QLA23XX(ha)) { host->max_id = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; ha->request_q_length = REQUEST_ENTRY_CNT_2200; ha->response_q_length = RESPONSE_ENTRY_CNT_2300; ha->last_loop_id = SNS_LAST_LOOP_ID_2300; - ha->isp_ops.pci_config = qla2300_pci_config; - ha->isp_ops.intr_handler = qla2300_intr_handler; - ha->isp_ops.fw_dump = qla2300_fw_dump; - ha->isp_ops.beacon_on = qla2x00_beacon_on; - ha->isp_ops.beacon_off = qla2x00_beacon_off; - ha->isp_ops.beacon_blink = qla2x00_beacon_blink; ha->gid_list_info_size = 6; if (IS_QLA2322(ha) || IS_QLA6322(ha)) ha->optrom_size = OPTROM_SIZE_2322; + ha->isp_ops = &qla2300_isp_ops; } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { host->max_id = MAX_TARGETS_2200; ha->mbx_count = MAILBOX_REGISTER_COUNT; @@ -1531,36 +1655,20 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->last_loop_id = SNS_LAST_LOOP_ID_2300; ha->init_cb_size = sizeof(struct mid_init_cb_24xx); ha->mgmt_svr_loop_id = 10 + ha->vp_idx; - ha->isp_ops.pci_config = qla24xx_pci_config; - ha->isp_ops.reset_chip = qla24xx_reset_chip; - ha->isp_ops.chip_diag = qla24xx_chip_diag; - ha->isp_ops.config_rings = qla24xx_config_rings; - ha->isp_ops.reset_adapter = qla24xx_reset_adapter; - ha->isp_ops.nvram_config = qla24xx_nvram_config; - ha->isp_ops.update_fw_options = qla24xx_update_fw_options; - ha->isp_ops.load_risc = qla24xx_load_risc; - ha->isp_ops.pci_info_str = qla24xx_pci_info_str; - ha->isp_ops.fw_version_str = qla24xx_fw_version_str; - ha->isp_ops.intr_handler = qla24xx_intr_handler; - ha->isp_ops.enable_intrs = qla24xx_enable_intrs; - ha->isp_ops.disable_intrs = qla24xx_disable_intrs; - ha->isp_ops.abort_command = qla24xx_abort_command; - ha->isp_ops.abort_target = qla24xx_abort_target; - ha->isp_ops.fabric_login = qla24xx_login_fabric; - ha->isp_ops.fabric_logout = qla24xx_fabric_logout; - ha->isp_ops.prep_ms_iocb = qla24xx_prep_ms_iocb; - ha->isp_ops.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb; - ha->isp_ops.read_nvram = qla24xx_read_nvram_data; - ha->isp_ops.write_nvram = qla24xx_write_nvram_data; - ha->isp_ops.fw_dump = qla24xx_fw_dump; - ha->isp_ops.read_optrom = qla24xx_read_optrom_data; - ha->isp_ops.write_optrom = qla24xx_write_optrom_data; - ha->isp_ops.beacon_on = qla24xx_beacon_on; - ha->isp_ops.beacon_off = qla24xx_beacon_off; - ha->isp_ops.beacon_blink = qla24xx_beacon_blink; - ha->isp_ops.get_flash_version = qla24xx_get_flash_version; ha->gid_list_info_size = 8; ha->optrom_size = OPTROM_SIZE_24XX; + ha->isp_ops = &qla24xx_isp_ops; + } else if (IS_QLA25XX(ha)) { + host->max_id = MAX_TARGETS_2200; + ha->mbx_count = MAILBOX_REGISTER_COUNT; + ha->request_q_length = REQUEST_ENTRY_CNT_24XX; + ha->response_q_length = RESPONSE_ENTRY_CNT_2300; + ha->last_loop_id = SNS_LAST_LOOP_ID_2300; + ha->init_cb_size = sizeof(struct mid_init_cb_24xx); + ha->mgmt_svr_loop_id = 10 + ha->vp_idx; + ha->gid_list_info_size = 8; + ha->optrom_size = OPTROM_SIZE_25XX; + ha->isp_ops = &qla25xx_isp_ops; } host->can_queue = ha->request_q_length + 128; @@ -1628,11 +1736,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n", ha->host_no, ha)); - ha->isp_ops.disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); spin_lock_irqsave(&ha->hardware_lock, flags); reg = ha->iobase; - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_HOST_INT); WRT_REG_DWORD(®->isp24.hccr, HCCRX_CLR_RISC_INT); } else { @@ -1654,7 +1762,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) } spin_unlock_irqrestore(&ha->hardware_lock, flags); - ha->isp_ops.enable_intrs(ha); + ha->isp_ops->enable_intrs(ha); pci_set_drvdata(pdev, ha); @@ -1679,9 +1787,9 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str, ha->model_number, ha->model_desc ? ha->model_desc: "", pdev->device, - ha->isp_ops.pci_info_str(ha, pci_info), pci_name(pdev), + ha->isp_ops->pci_info_str(ha, pci_info), pci_name(pdev), ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, - ha->isp_ops.fw_version_str(ha, fw_str)); + ha->isp_ops->fw_version_str(ha, fw_str)); return 0; @@ -1747,7 +1855,7 @@ qla2x00_free_device(scsi_qla_host_t *ha) /* turn-off interrupts on the card */ if (ha->interrupts_on) - ha->isp_ops.disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); qla2x00_mem_free(ha); @@ -2025,7 +2133,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) } memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt)); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { + if (IS_FWI2_CAPABLE(ha)) { /* * Get consistent memory allocated for SFP * block. @@ -2046,6 +2154,19 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) } } + /* Get memory for cached NVRAM */ + ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); + if (ha->nvram == NULL) { + /* error */ + qla_printk(KERN_WARNING, ha, + "Memory Allocation failed - nvram cache\n"); + + qla2x00_mem_free(ha); + msleep(100); + + continue; + } + /* Done all allocations without any error. */ status = 0; @@ -2158,6 +2279,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha) ha->fw_dump_reading = 0; vfree(ha->optrom_buffer); + kfree(ha->nvram); } /* @@ -2305,7 +2427,7 @@ qla2x00_do_dpc(void *data) if (fcport->flags & FCF_FABRIC_DEVICE) { if (fcport->flags & FCF_TAPE_PRESENT) - ha->isp_ops.fabric_logout( + ha->isp_ops->fabric_logout( ha, fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area, @@ -2385,10 +2507,10 @@ qla2x00_do_dpc(void *data) } if (!ha->interrupts_on) - ha->isp_ops.enable_intrs(ha); + ha->isp_ops->enable_intrs(ha); if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) - ha->isp_ops.beacon_blink(ha); + ha->isp_ops->beacon_blink(ha); qla2x00_do_dpc_all_vps(ha); @@ -2617,18 +2739,20 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout) /* Firmware interface routines. */ -#define FW_BLOBS 5 +#define FW_BLOBS 6 #define FW_ISP21XX 0 #define FW_ISP22XX 1 #define FW_ISP2300 2 #define FW_ISP2322 3 #define FW_ISP24XX 4 +#define FW_ISP25XX 5 #define FW_FILE_ISP21XX "ql2100_fw.bin" #define FW_FILE_ISP22XX "ql2200_fw.bin" #define FW_FILE_ISP2300 "ql2300_fw.bin" #define FW_FILE_ISP2322 "ql2322_fw.bin" #define FW_FILE_ISP24XX "ql2400_fw.bin" +#define FW_FILE_ISP25XX "ql2500_fw.bin" static DECLARE_MUTEX(qla_fw_lock); @@ -2638,6 +2762,7 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = { { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, }, { .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, { .name = FW_FILE_ISP24XX, }, + { .name = FW_FILE_ISP25XX, }, }; struct fw_blob * @@ -2656,6 +2781,8 @@ qla2x00_request_firmware(scsi_qla_host_t *ha) blob = &qla_fw_blobs[FW_ISP2322]; } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { blob = &qla_fw_blobs[FW_ISP24XX]; + } else if (IS_QLA25XX(ha)) { + blob = &qla_fw_blobs[FW_ISP25XX]; } down(&qla_fw_lock); @@ -2699,6 +2826,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) }, + { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) }, { 0 }, }; MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); @@ -2723,7 +2851,7 @@ qla2x00_module_init(void) /* Allocate cache for SRBs. */ srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); + SLAB_HWCACHE_ALIGN, NULL); if (srb_cachep == NULL) { printk(KERN_ERR "qla2xxx: Unable to allocate SRB cache...Failing load!\n"); diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 206bda093da..a925a3f179f 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -766,6 +766,29 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, return ret; } +uint8_t * +qla25xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, + uint32_t bytes) +{ + uint32_t i; + uint32_t *dwptr; + + /* Dword reads to flash. */ + dwptr = (uint32_t *)buf; + for (i = 0; i < bytes >> 2; i++, naddr++) + dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, + flash_data_to_access_addr(FA_VPD_NVRAM_ADDR | naddr))); + + return buf; +} + +int +qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, + uint32_t bytes) +{ + return qla24xx_write_flash_data(ha, (uint32_t *)buf, + FA_VPD_NVRAM_ADDR | naddr, bytes >> 2); +} static inline void qla2x00_flip_colors(scsi_qla_host_t *ha, uint16_t *pflags) @@ -919,7 +942,7 @@ qla2x00_beacon_off(struct scsi_qla_host *ha) else ha->beacon_color_state = QLA_LED_GRN_ON; - ha->isp_ops.beacon_blink(ha); /* This turns green LED off */ + ha->isp_ops->beacon_blink(ha); /* This turns green LED off */ ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING; ha->fw_options[1] &= ~FO1_DISABLE_GPIO6_7; @@ -1031,7 +1054,7 @@ qla24xx_beacon_off(struct scsi_qla_host *ha) ha->beacon_blink_led = 0; ha->beacon_color_state = QLA_LED_ALL_ON; - ha->isp_ops.beacon_blink(ha); /* Will flip to all off. */ + ha->isp_ops->beacon_blink(ha); /* Will flip to all off. */ /* Give control back to firmware. */ spin_lock_irqsave(&ha->hardware_lock, flags); @@ -1419,7 +1442,7 @@ qla2x00_suspend_hba(struct scsi_qla_host *ha) /* Suspend HBA. */ scsi_block_requests(ha->host); - ha->isp_ops.disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Pause RISC. */ @@ -1705,7 +1728,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, { /* Suspend HBA. */ scsi_block_requests(ha->host); - ha->isp_ops.disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with read. */ @@ -1713,7 +1736,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, /* Resume HBA. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); - ha->isp_ops.enable_intrs(ha); + ha->isp_ops->enable_intrs(ha); scsi_unblock_requests(ha->host); return buf; @@ -1727,7 +1750,7 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, /* Suspend HBA. */ scsi_block_requests(ha->host); - ha->isp_ops.disable_intrs(ha); + ha->isp_ops->disable_intrs(ha); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with write. */ diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index fd2f10a2534..18095b9b76f 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.00-k1" +#define QLA2XXX_VERSION "8.02.00-k3" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index e69160a7bc6..b1d565c12c5 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1677,7 +1677,7 @@ static int __init qla4xxx_module_init(void) /* Allocate cache for SRBs. */ srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); + SLAB_HWCACHE_ALIGN, NULL); if (srb_cachep == NULL) { printk(KERN_ERR "%s: Unable to allocate SRB cache..." diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index c4195ea869e..594887205b0 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -193,7 +193,8 @@ static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int f cpu_relax(); } if (!loop_count) - printk(KERN_EMERG "qlogicpti: mbox_command loop timeout #1\n"); + printk(KERN_EMERG "qlogicpti%d: mbox_command loop timeout #1\n", + qpti->qpti_id); /* Write mailbox command registers. */ switch (mbox_param[param[0]] >> 4) { @@ -224,8 +225,8 @@ static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int f (sbus_readw(qpti->qregs + HCCTRL) & HCCTRL_CRIRQ)) udelay(20); if (!loop_count) - printk(KERN_EMERG "qlogicpti: mbox_command[%04x] loop timeout #2\n", - param[0]); + printk(KERN_EMERG "qlogicpti%d: mbox_command[%04x] loop timeout #2\n", + qpti->qpti_id, param[0]); /* Wait for SBUS semaphore to get set. */ loop_count = DEFAULT_LOOP_COUNT; @@ -238,16 +239,16 @@ static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int f break; } if (!loop_count) - printk(KERN_EMERG "qlogicpti: mbox_command[%04x] loop timeout #3\n", - param[0]); + printk(KERN_EMERG "qlogicpti%d: mbox_command[%04x] loop timeout #3\n", + qpti->qpti_id, param[0]); /* Wait for MBOX busy condition to go away. */ loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && (sbus_readw(qpti->qregs + MBOX0) == 0x04)) udelay(20); if (!loop_count) - printk(KERN_EMERG "qlogicpti: mbox_command[%04x] loop timeout #4\n", - param[0]); + printk(KERN_EMERG "qlogicpti%d: mbox_command[%04x] loop timeout #4\n", + qpti->qpti_id, param[0]); /* Read back output parameters. */ switch (mbox_param[param[0]] & 0xf) { @@ -342,7 +343,8 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) while (--loop_count && ((sbus_readw(qpti->qregs + MBOX0) & 0xff) == 0x04)) udelay(20); if (!loop_count) - printk(KERN_EMERG "qlogicpti: reset_hardware loop timeout\n"); + printk(KERN_EMERG "qlogicpti%d: reset_hardware loop timeout\n", + qpti->qpti_id); sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL); set_sbus_cfg1(qpti); @@ -721,12 +723,12 @@ static int __init qpti_register_irq(struct qlogicpti *qpti) IRQF_SHARED, "Qlogic/PTI", qpti)) goto fail; - printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->irq); + printk("qlogicpti%d: IRQ %d ", qpti->qpti_id, qpti->irq); return 0; fail: - printk("qpti%d: Cannot acquire irq line\n", qpti->qpti_id); + printk("qlogicpti%d: Cannot acquire irq line\n", qpti->qpti_id); return -1; } @@ -1210,7 +1212,7 @@ static int qlogicpti_return_status(struct Status_Entry *sts, int id) host_status = DID_OK; break; default: - printk(KERN_EMERG "qpti%d: unknown completion status 0x%04x\n", + printk(KERN_EMERG "qlogicpti%d: unknown completion status 0x%04x\n", id, sts->completion_status); host_status = DID_ERROR; break; @@ -1329,8 +1331,8 @@ static int qlogicpti_abort(struct scsi_cmnd *Cmnd) u32 cmd_cookie; int i; - printk(KERN_WARNING "qlogicpti : Aborting cmd for tgt[%d] lun[%d]\n", - (int)Cmnd->device->id, (int)Cmnd->device->lun); + printk(KERN_WARNING "qlogicpti%d: Aborting cmd for tgt[%d] lun[%d]\n", + qpti->qpti_id, (int)Cmnd->device->id, (int)Cmnd->device->lun); qlogicpti_disable_irqs(qpti); @@ -1348,7 +1350,8 @@ static int qlogicpti_abort(struct scsi_cmnd *Cmnd) param[3] = cmd_cookie & 0xffff; if (qlogicpti_mbox_command(qpti, param, 0) || (param[0] != MBOX_COMMAND_COMPLETE)) { - printk(KERN_EMERG "qlogicpti : scsi abort failure: %x\n", param[0]); + printk(KERN_EMERG "qlogicpti%d: scsi abort failure: %x\n", + qpti->qpti_id, param[0]); return_status = FAILED; } @@ -1364,7 +1367,8 @@ static int qlogicpti_reset(struct scsi_cmnd *Cmnd) struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata; int return_status = SUCCESS; - printk(KERN_WARNING "qlogicpti : Resetting SCSI bus!\n"); + printk(KERN_WARNING "qlogicpti%d: Resetting SCSI bus!\n", + qpti->qpti_id); qlogicpti_disable_irqs(qpti); @@ -1372,7 +1376,8 @@ static int qlogicpti_reset(struct scsi_cmnd *Cmnd) param[1] = qpti->host_param.bus_reset_delay; if (qlogicpti_mbox_command(qpti, param, 0) || (param[0] != MBOX_COMMAND_COMPLETE)) { - printk(KERN_EMERG "qlogicisp : scsi bus reset failure: %x\n", param[0]); + printk(KERN_EMERG "qlogicisp%d: scsi bus reset failure: %x\n", + qpti->qpti_id, param[0]); return_status = FAILED; } @@ -1454,22 +1459,25 @@ static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_devi if (qlogicpti_reset_hardware(host)) goto fail_unmap_queues; - if (scsi_add_host(host, &dev->dev)) - goto fail_unmap_queues; - printk("(Firmware v%d.%d.%d)", qpti->fware_majrev, qpti->fware_minrev, qpti->fware_micrev); fcode = of_get_property(dp, "isp-fcode", NULL); if (fcode && fcode[0]) - printk("(Firmware %s)", fcode); + printk("(FCode %s)", fcode); if (of_find_property(dp, "differential", NULL) != NULL) qpti->differential = 1; - printk (" [%s Wide, using %s interface]\n", + printk("\nqlogicpti%d: [%s Wide, using %s interface]\n", + qpti->qpti_id, (qpti->ultra ? "Ultra" : "Fast"), (qpti->differential ? "differential" : "single ended")); + if (scsi_add_host(host, &dev->dev)) { + printk("qlogicpti%d: Failed scsi_add_host\n", qpti->qpti_id); + goto fail_unmap_queues; + } + dev_set_drvdata(&sdev->ofdev.dev, qpti); qpti_chain_add(qpti); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a691dda40d2..a5de1a829a7 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -288,7 +288,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost) if (!pool->users) { pool->slab = kmem_cache_create(pool->name, sizeof(struct scsi_cmnd), 0, - pool->slab_flags, NULL, NULL); + pool->slab_flags, NULL); if (!pool->slab) goto fail; } diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 4cd9c58efef..4947dfe625a 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -2875,7 +2875,7 @@ static int __init scsi_debug_init(void) init_all_queued(); - sdebug_driver_template.proc_name = (char *)sdebug_proc_name; + sdebug_driver_template.proc_name = sdebug_proc_name; host_to_add = scsi_debug_add_host; scsi_debug_add_host = 0; diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 19c44f0781f..e2ea739e33d 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -154,6 +154,9 @@ static struct { {"EMC", "Invista", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, {"EMULEX", "MD21/S2 ESDI", NULL, BLIST_SINGLELUN}, + {"easyRAID", "16P", NULL, BLIST_NOREPORTLUN}, + {"easyRAID", "X6P", NULL, BLIST_NOREPORTLUN}, + {"easyRAID", "F8", NULL, BLIST_NOREPORTLUN}, {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, {"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN | BLIST_INQUIRY_36}, {"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN | BLIST_INQUIRY_36}, diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1f5a07bf2a7..604f4d71793 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -263,25 +263,12 @@ static int scsi_merge_bio(struct request *rq, struct bio *bio) bio->bi_rw |= (1 << BIO_RW); blk_queue_bounce(q, &bio); - if (!rq->bio) - blk_rq_bio_prep(q, rq, bio); - else if (!ll_back_merge_fn(q, rq, bio)) - return -EINVAL; - else { - rq->biotail->bi_next = bio; - rq->biotail = bio; - } - - return 0; + return blk_rq_append_bio(q, rq, bio); } -static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error) +static void scsi_bi_endio(struct bio *bio, int error) { - if (bio->bi_size) - return 1; - bio_put(bio); - return 0; } /** @@ -337,7 +324,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, if (bio->bi_vcnt >= nr_vecs) { err = scsi_merge_bio(rq, bio); if (err) { - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); goto free_bios; } bio = NULL; @@ -359,7 +346,7 @@ free_bios: /* * call endio instead of bio_put incase it was bounced */ - bio_endio(bio, bio->bi_size, 0); + bio_endio(bio, 0); } return err; @@ -654,7 +641,7 @@ void scsi_run_host_queues(struct Scsi_Host *shost) static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, int bytes, int requeue) { - request_queue_t *q = cmd->device->request_queue; + struct request_queue *q = cmd->device->request_queue; struct request *req = cmd->request; unsigned long flags; @@ -818,7 +805,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) { int result = cmd->result; int this_count = cmd->request_bufflen; - request_queue_t *q = cmd->device->request_queue; + struct request_queue *q = cmd->device->request_queue; struct request *req = cmd->request; int clear_errors = 1; struct scsi_sense_hdr sshdr; @@ -1038,22 +1025,6 @@ static int scsi_init_io(struct scsi_cmnd *cmd) return BLKPREP_KILL; } -static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, - sector_t *error_sector) -{ - struct scsi_device *sdev = q->queuedata; - struct scsi_driver *drv; - - if (sdev->sdev_state != SDEV_RUNNING) - return -ENXIO; - - drv = *(struct scsi_driver **) disk->private_data; - if (drv->issue_flush) - return drv->issue_flush(&sdev->sdev_gendev, error_sector); - - return -EOPNOTSUPP; -} - static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, struct request *req) { @@ -1340,7 +1311,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, /* * Kill a request for a dead device */ -static void scsi_kill_request(struct request *req, request_queue_t *q) +static void scsi_kill_request(struct request *req, struct request_queue *q) { struct scsi_cmnd *cmd = req->special; struct scsi_device *sdev = cmd->device; @@ -1596,7 +1567,6 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) return NULL; blk_queue_prep_rq(q, scsi_prep_fn); - blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); blk_queue_softirq_done(q, scsi_softirq_done); return q; } @@ -1661,7 +1631,7 @@ int __init scsi_init_queue(void) scsi_io_context_cache = kmem_cache_create("scsi_io_context", sizeof(struct scsi_io_context), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!scsi_io_context_cache) { printk(KERN_ERR "SCSI: can't init scsi io context cache\n"); return -ENOMEM; @@ -1672,7 +1642,7 @@ int __init scsi_init_queue(void) int size = sgp->size * sizeof(struct scatterlist); sgp->slab = kmem_cache_create(sgp->name, size, 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); + SLAB_HWCACHE_ALIGN, NULL); if (!sgp->slab) { printk(KERN_ERR "SCSI: can't init sg slab %s\n", sgp->name); @@ -2119,7 +2089,7 @@ EXPORT_SYMBOL(scsi_target_resume); int scsi_internal_device_block(struct scsi_device *sdev) { - request_queue_t *q = sdev->request_queue; + struct request_queue *q = sdev->request_queue; unsigned long flags; int err = 0; @@ -2159,7 +2129,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block); int scsi_internal_device_unblock(struct scsi_device *sdev) { - request_queue_t *q = sdev->request_queue; + struct request_queue *q = sdev->request_queue; int err; unsigned long flags; diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index 4bf9aa547c7..40579edca10 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c @@ -64,7 +64,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb) if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { err = -EBADMSG; - goto next_msg; + return; } hdr = NLMSG_DATA(nlh); @@ -99,27 +99,6 @@ next_msg: /** - * scsi_nl_rcv_msg - - * Receive handler for a socket. Extracts a received message buffer from - * the socket, and starts message processing. - * - * @sk: socket - * @len: unused - * - **/ -static void -scsi_nl_rcv(struct sock *sk, int len) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(&sk->sk_receive_queue))) { - scsi_nl_rcv_msg(skb); - kfree_skb(skb); - } -} - - -/** * scsi_nl_rcv_event - * Event handler for a netlink socket. * @@ -167,8 +146,8 @@ scsi_netlink_init(void) return; } - scsi_nl_sock = netlink_kernel_create(NETLINK_SCSITRANSPORT, - SCSI_NL_GRP_CNT, scsi_nl_rcv, NULL, + scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT, + SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL, THIS_MODULE); if (!scsi_nl_sock) { printk(KERN_ERR "%s: register of recieve handler failed\n", diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c index 6cfaaa2d0c8..63a30f566f3 100644 --- a/drivers/scsi/scsi_sysctl.c +++ b/drivers/scsi/scsi_sysctl.c @@ -9,6 +9,7 @@ #include <linux/sysctl.h> #include "scsi_logging.h" +#include "scsi_priv.h" static ctl_table scsi_table[] = { diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ed720863ab9..ede9986d349 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -16,6 +16,7 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> #include <scsi/scsi_transport.h> +#include <scsi/scsi_driver.h> #include "scsi_priv.h" #include "scsi_logging.h" @@ -276,16 +277,11 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } -static int scsi_bus_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct scsi_device *sdev = to_scsi_device(dev); - int i = 0; - int length = 0; - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); - envp[i] = NULL; + add_uevent_var(env, "MODALIAS=" SCSI_DEVICE_MODALIAS_FMT, sdev->type); return 0; } @@ -714,6 +710,7 @@ static int attr_add(struct device *dev, struct device_attribute *attr) int scsi_sysfs_add_sdev(struct scsi_device *sdev) { int error, i; + struct request_queue *rq = sdev->request_queue; if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0) return error; @@ -733,6 +730,17 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) /* take a reference for the sdev_classdev; this is * released by the sdev_class .release */ get_device(&sdev->sdev_gendev); + + error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL); + + if (error) + sdev_printk(KERN_INFO, sdev, + "Failed to register bsg queue, errno=%d\n", error); + + /* we're treating error on bsg register as non-fatal, so pretend + * nothing went wrong */ + error = 0; + if (sdev->host->hostt->sdev_attrs) { for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) { error = attr_add(&sdev->sdev_gendev, @@ -779,6 +787,7 @@ void __scsi_remove_device(struct scsi_device *sdev) if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0) return; + bsg_unregister_queue(sdev->request_queue); class_device_unregister(&sdev->sdev_classdev); transport_remove_device(dev); device_del(dev); @@ -803,7 +812,7 @@ void scsi_remove_device(struct scsi_device *sdev) } 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 --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 2570f48a69c..371b69c110b 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -585,7 +585,7 @@ static int __init scsi_tgt_init(void) scsi_tgt_cmd_cache = kmem_cache_create("scsi_tgt_cmd", sizeof(struct scsi_tgt_cmd), - 0, 0, NULL, NULL); + 0, 0, NULL); if (!scsi_tgt_cmd_cache) return -ENOMEM; diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index e8825709797..47057254850 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2358,7 +2358,7 @@ fc_rport_final_delete(struct work_struct *work) * 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 --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 34c1860a259..5428d15f23c 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1097,61 +1097,49 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) } /* - * Get message from skb (based on rtnetlink_rcv_skb). Each message is - * processed by iscsi_if_recv_msg. Malformed skbs with wrong lengths or - * invalid creds are discarded silently. + * Get message from skb. Each message is processed by iscsi_if_recv_msg. + * Malformed skbs with wrong lengths or invalid creds are not processed. */ static void -iscsi_if_rx(struct sock *sk, int len) +iscsi_if_rx(struct sk_buff *skb) { - struct sk_buff *skb; - mutex_lock(&rx_queue_mutex); - while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { - if (NETLINK_CREDS(skb)->uid) { - skb_pull(skb, skb->len); - goto free_skb; + while (skb->len >= NLMSG_SPACE(0)) { + int err; + uint32_t rlen; + struct nlmsghdr *nlh; + struct iscsi_uevent *ev; + + nlh = nlmsg_hdr(skb); + if (nlh->nlmsg_len < sizeof(*nlh) || + skb->len < nlh->nlmsg_len) { + break; } - while (skb->len >= NLMSG_SPACE(0)) { - int err; - uint32_t rlen; - struct nlmsghdr *nlh; - struct iscsi_uevent *ev; + ev = NLMSG_DATA(nlh); + rlen = NLMSG_ALIGN(nlh->nlmsg_len); + if (rlen > skb->len) + rlen = skb->len; - nlh = nlmsg_hdr(skb); - if (nlh->nlmsg_len < sizeof(*nlh) || - skb->len < nlh->nlmsg_len) { - break; - } - - ev = NLMSG_DATA(nlh); - rlen = NLMSG_ALIGN(nlh->nlmsg_len); - if (rlen > skb->len) - rlen = skb->len; - - err = iscsi_if_recv_msg(skb, nlh); - if (err) { - ev->type = ISCSI_KEVENT_IF_ERROR; - ev->iferror = err; - } - do { - /* - * special case for GET_STATS: - * on success - sending reply and stats from - * inside of if_recv_msg(), - * on error - fall through. - */ - if (ev->type == ISCSI_UEVENT_GET_STATS && !err) - break; - err = iscsi_if_send_reply( - NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, - nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); - } while (err < 0 && err != -ECONNREFUSED); - skb_pull(skb, rlen); + err = iscsi_if_recv_msg(skb, nlh); + if (err) { + ev->type = ISCSI_KEVENT_IF_ERROR; + ev->iferror = err; } -free_skb: - kfree_skb(skb); + do { + /* + * special case for GET_STATS: + * on success - sending reply and stats from + * inside of if_recv_msg(), + * on error - fall through. + */ + if (ev->type == ISCSI_UEVENT_GET_STATS && !err) + break; + err = iscsi_if_send_reply( + NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, + nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); + } while (err < 0 && err != -ECONNREFUSED); + skb_pull(skb, rlen); } mutex_unlock(&rx_queue_mutex); } @@ -1523,7 +1511,7 @@ static __init int iscsi_transport_init(void) if (err) goto unregister_conn_class; - nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, NULL, + nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL, THIS_MODULE); if (!nls) { err = -ENOBUFS; diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index b2ef71a8629..3120f4b3a11 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -29,6 +29,8 @@ #include <linux/err.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/blkdev.h> +#include <linux/bsg.h> #include <scsi/scsi.h> #include <scsi/scsi_device.h> @@ -40,6 +42,7 @@ struct sas_host_attrs { struct list_head rphy_list; struct mutex lock; + struct request_queue *q; u32 next_target_id; u32 next_expander_id; int next_port_id; @@ -152,6 +155,106 @@ static struct { sas_bitfield_name_search(linkspeed, sas_linkspeed_names) sas_bitfield_name_set(linkspeed, sas_linkspeed_names) +static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, + struct sas_rphy *rphy) +{ + struct request *req; + int ret; + int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *); + + while (!blk_queue_plugged(q)) { + req = elv_next_request(q); + if (!req) + break; + + blkdev_dequeue_request(req); + + spin_unlock_irq(q->queue_lock); + + handler = to_sas_internal(shost->transportt)->f->smp_handler; + ret = handler(shost, rphy, req); + + spin_lock_irq(q->queue_lock); + + req->end_io(req, ret); + } +} + +static void sas_host_smp_request(struct request_queue *q) +{ + sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL); +} + +static void sas_non_host_smp_request(struct request_queue *q) +{ + struct sas_rphy *rphy = q->queuedata; + sas_smp_request(q, rphy_to_shost(rphy), rphy); +} + +static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) +{ + struct request_queue *q; + int error; + struct device *dev; + char namebuf[BUS_ID_SIZE]; + const char *name; + + if (!to_sas_internal(shost->transportt)->f->smp_handler) { + printk("%s can't handle SMP requests\n", shost->hostt->name); + return 0; + } + + if (rphy) { + q = blk_init_queue(sas_non_host_smp_request, NULL); + dev = &rphy->dev; + name = dev->bus_id; + } else { + q = blk_init_queue(sas_host_smp_request, NULL); + dev = &shost->shost_gendev; + snprintf(namebuf, sizeof(namebuf), + "sas_host%d", shost->host_no); + name = namebuf; + } + if (!q) + return -ENOMEM; + + error = bsg_register_queue(q, dev, name); + if (error) { + blk_cleanup_queue(q); + return -ENOMEM; + } + + if (rphy) + rphy->q = q; + else + to_sas_host_attrs(shost)->q = q; + + if (rphy) + q->queuedata = rphy; + else + q->queuedata = shost; + + set_bit(QUEUE_FLAG_BIDI, &q->queue_flags); + + return 0; +} + +static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy) +{ + struct request_queue *q; + + if (rphy) + q = rphy->q; + else + q = to_sas_host_attrs(shost)->q; + + if (!q) + return; + + bsg_unregister_queue(q); + blk_cleanup_queue(q); +} + /* * SAS host attributes */ @@ -167,11 +270,26 @@ static int sas_host_setup(struct transport_container *tc, struct device *dev, sas_host->next_target_id = 0; sas_host->next_expander_id = 0; sas_host->next_port_id = 0; + + if (sas_bsg_initialize(shost, NULL)) + dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n", + shost->host_no); + + return 0; +} + +static int sas_host_remove(struct transport_container *tc, struct device *dev, + struct class_device *cdev) +{ + struct Scsi_Host *shost = dev_to_shost(dev); + + sas_bsg_remove(shost, NULL); + return 0; } static DECLARE_TRANSPORT_CLASS(sas_host_class, - "sas_host", sas_host_setup, NULL, NULL); + "sas_host", sas_host_setup, sas_host_remove, NULL); static int sas_host_match(struct attribute_container *cont, struct device *dev) @@ -1287,6 +1405,9 @@ int sas_rphy_add(struct sas_rphy *rphy) return error; transport_add_device(&rphy->dev); transport_configure_device(&rphy->dev); + if (sas_bsg_initialize(shost, rphy)) + printk("fail to a bsg device %s\n", rphy->dev.bus_id); + mutex_lock(&sas_host->lock); list_add_tail(&rphy->list, &sas_host->rphy_list); @@ -1329,6 +1450,8 @@ void sas_rphy_free(struct sas_rphy *rphy) list_del(&rphy->list); mutex_unlock(&sas_host->lock); + sas_bsg_remove(shost, rphy); + transport_destroy_device(dev); put_device(dev); diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 6f56f875063..4df21c92ff1 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -787,10 +787,12 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) struct scsi_target *starget = sdev->sdev_target; struct Scsi_Host *shost = sdev->host; int len = sdev->inquiry_len; + int min_period = spi_min_period(starget); + int max_width = spi_max_width(starget); /* first set us up for narrow async */ DV_SET(offset, 0); DV_SET(width, 0); - + if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS) != SPI_COMPARE_SUCCESS) { starget_printk(KERN_ERR, starget, "Domain Validation Initial Inquiry Failed\n"); @@ -798,9 +800,13 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) return; } + if (!scsi_device_wide(sdev)) { + spi_max_width(starget) = 0; + max_width = 0; + } + /* test width */ - if (i->f->set_width && spi_max_width(starget) && - scsi_device_wide(sdev)) { + if (i->f->set_width && max_width) { i->f->set_width(starget, 1); if (spi_dv_device_compare_inquiry(sdev, buffer, @@ -809,6 +815,11 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) != SPI_COMPARE_SUCCESS) { starget_printk(KERN_ERR, starget, "Wide Transfers Fail\n"); i->f->set_width(starget, 0); + /* Make sure we don't force wide back on by asking + * for a transfer period that requires it */ + max_width = 0; + if (min_period < 10) + min_period = 10; } } @@ -828,7 +839,8 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) /* now set up to the maximum */ DV_SET(offset, spi_max_offset(starget)); - DV_SET(period, spi_min_period(starget)); + DV_SET(period, min_period); + /* try QAS requests; this should be harmless to set if the * target supports it */ if (scsi_device_qas(sdev)) { @@ -837,14 +849,14 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) DV_SET(qas, 0); } - if (scsi_device_ius(sdev) && spi_min_period(starget) < 9) { + if (scsi_device_ius(sdev) && min_period < 9) { /* This u320 (or u640). Set IU transfers */ DV_SET(iu, 1); /* Then set the optional parameters */ DV_SET(rd_strm, 1); DV_SET(wr_flow, 1); DV_SET(rti, 1); - if (spi_min_period(starget) == 8) + if (min_period == 8) DV_SET(pcomp_en, 1); } else { DV_SET(iu, 0); @@ -862,6 +874,10 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) } else { DV_SET(dt, 1); } + /* set width last because it will pull all the other + * parameters down to required values */ + DV_SET(width, max_width); + /* Do the read only INQUIRY tests */ spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len, spi_dv_device_compare_inquiry); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 424d557284a..2c6116fd457 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -241,7 +241,6 @@ static struct scsi_driver sd_template = { }, .rescan = sd_rescan, .init_command = sd_init_command, - .issue_flush = sd_issue_flush, }; /* @@ -800,10 +799,17 @@ static int sd_sync_cache(struct scsi_disk *sdkp) return 0; } -static int sd_issue_flush(struct device *dev, sector_t *error_sector) +static int sd_issue_flush(struct request_queue *q, struct gendisk *disk, + sector_t *error_sector) { int ret = 0; - struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); + struct scsi_device *sdp = q->queuedata; + struct scsi_disk *sdkp; + + if (sdp->sdev_state != SDEV_RUNNING) + return -ENXIO; + + sdkp = scsi_disk_get_from_dev(&sdp->sdev_gendev); if (!sdkp) return -ENODEV; @@ -814,7 +820,7 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector) return ret; } -static void sd_prepare_flush(request_queue_t *q, struct request *rq) +static void sd_prepare_flush(struct request_queue *q, struct request *rq) { memset(rq->cmd, 0, sizeof(rq->cmd)); rq->cmd_type = REQ_TYPE_BLOCK_PC; @@ -1285,7 +1291,7 @@ got_data: */ int hard_sector = sector_size; sector_t sz = (sdkp->capacity/2) * (hard_sector/256); - request_queue_t *queue = sdp->request_queue; + struct request_queue *queue = sdp->request_queue; sector_t mb = sz; blk_queue_hardsect_size(queue, hard_sector); @@ -1663,6 +1669,8 @@ static int sd_probe(struct device *dev) sd_revalidate_disk(gd); + blk_queue_issue_flush_fn(sdp->request_queue, sd_issue_flush); + gd->driverfs_dev = &sdp->sdev_gendev; gd->flags = GENHD_FL_DRIVERFS; if (sdp->removable) diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index ff62e9708e1..ce80fa9ad81 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -420,7 +420,7 @@ static inline void borken_wait (void) #define ULOOP( i ) for (clock = i*8;;) #define TIMEOUT (!(clock--)) -int __init seagate_st0x_detect (struct scsi_host_template * tpnt) +static int __init seagate_st0x_detect (struct scsi_host_template * tpnt) { struct Scsi_Host *instance; int i, j; diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c index 018c65f73ac..d63d229e232 100644 --- a/drivers/scsi/sim710.c +++ b/drivers/scsi/sim710.c @@ -100,7 +100,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, { struct Scsi_Host * host = NULL; struct NCR_700_Host_Parameters *hostdata = - kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); printk(KERN_NOTICE "sim710: %s\n", dev->bus_id); printk(KERN_NOTICE "sim710: irq = %d, clock = %d, base = 0x%lx, scsi_id = %d\n", @@ -110,7 +110,6 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, printk(KERN_ERR "sim710: Failed to allocate host data\n"); goto out; } - memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); if(request_region(base_addr, 64, "sim710") == NULL) { printk(KERN_ERR "sim710: Failed to reserve IO region 0x%lx\n", @@ -139,6 +138,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, goto out_put_host; } + dev_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -156,7 +156,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr, static __devexit int sim710_device_remove(struct device *dev) { - struct Scsi_Host *host = dev_to_shost(dev); + struct Scsi_Host *host = dev_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)host->hostdata[0]; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 5143c899084..902eb11ffe8 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -175,7 +175,7 @@ static void scsi_cd_put(struct scsi_cd *cd) * 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; @@ -624,7 +624,7 @@ static void get_sectorsize(struct scsi_cd *cd) unsigned char *buffer; int the_result, retries = 3; int sector_size; - request_queue_t *queue; + struct request_queue *queue; buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index a4f7b846577..73c44cbdea4 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1485,7 +1485,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) struct st_buffer *STbp; char *name = tape_name(STp); - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; retval = rw_checks(STp, filp, count); @@ -1736,7 +1736,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (SRpnt != NULL) st_release_request(SRpnt); release_buffering(STp, 0); - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -1942,7 +1942,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) struct st_buffer *STbp = STp->buffer; DEB( char *name = tape_name(STp); ) - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; retval = rw_checks(STp, filp, count); @@ -2069,7 +2069,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) release_buffering(STp, 1); STbp->buffer_bytes = 0; } - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -3226,7 +3226,7 @@ static int st_ioctl(struct inode *inode, struct file *file, char *name = tape_name(STp); void __user *p = (void __user *)arg; - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; DEB( @@ -3537,7 +3537,7 @@ static int st_ioctl(struct inode *inode, struct file *file, retval = (-EFAULT); goto out; } - up(&STp->lock); + mutex_unlock(&STp->lock); switch (cmd_in) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: @@ -3563,7 +3563,7 @@ static int st_ioctl(struct inode *inode, struct file *file, return retval; out: - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -4029,7 +4029,7 @@ static int st_probe(struct device *dev) tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0; - init_MUTEX(&tpnt->lock); + mutex_init(&tpnt->lock); st_nr_dev++; write_unlock(&st_dev_arr_lock); diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 50f3deb1f9e..6c807571297 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -3,6 +3,7 @@ #define _ST_H #include <linux/completion.h> +#include <linux/mutex.h> #include <linux/kref.h> #include <scsi/scsi_cmnd.h> @@ -98,7 +99,7 @@ struct st_partstat { struct scsi_tape { struct scsi_driver *driver; struct scsi_device *device; - struct semaphore lock; /* For serialization */ + struct mutex lock; /* For serialization */ struct completion wait; /* For SCSI commands */ struct st_buffer *buffer; diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 15a51459c81..3db22325ea2 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -2033,7 +2033,7 @@ static struct pci_device_id sym2_id_table[] __devinitdata = { { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C875, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C1510, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, /* new */ + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SCSI<<8, 0xffff00, 0UL }, /* new */ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C895A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C875A, diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 14cba1ca38b..5db1520f8ba 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -2082,10 +2082,9 @@ static int dc390_slave_alloc(struct scsi_device *scsi_device) uint id = scsi_device->id; uint lun = scsi_device->lun; - pDCB = kmalloc(sizeof(struct dc390_dcb), GFP_KERNEL); + pDCB = kzalloc(sizeof(struct dc390_dcb), GFP_KERNEL); if (!pDCB) return -ENOMEM; - memset(pDCB, 0, sizeof(struct dc390_dcb)); if (!pACB->DCBCnt++) { pACB->pLinkDCB = pDCB; diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index fa4e08e508a..b92ff047af3 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -89,6 +89,8 @@ #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> +#include <asm/irq.h> + #include "wd33c93.h" #define optimum_sx_per(hostdata) (hostdata)->sx_table[1].period_ns @@ -1762,7 +1764,7 @@ static char setup_buffer[SETUP_BUFFER_SIZE]; static char setup_used[MAX_SETUP_ARGS]; static int done_setup = 0; -int +static int wd33c93_setup(char *str) { int i; diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index 50703877a58..c822debc266 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c @@ -130,6 +130,7 @@ static int __devinit zorro7xx_init_one(struct zorro_dev *z, goto out_put_host; } + zorro_set_drvdata(z, host); scsi_scan_host(host); return 0; @@ -148,7 +149,7 @@ static int __devinit zorro7xx_init_one(struct zorro_dev *z, static __devexit void zorro7xx_remove_one(struct zorro_dev *z) { - struct Scsi_Host *host = dev_to_shost(&z->dev); + struct Scsi_Host *host = zorro_get_drvdata(z); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); scsi_remove_host(host); |