aic94xx: update BIOS image from user space.
PATCH 1/1 aic94xx: update BIOS image from user space.
1. Create a file "update_bios" in sysfs to allow user to update bios from user space.
2. The BIOS image file can be downloaded from web site "http://www.adaptec.com/en-US/downloads/bios_fw/bios_fw_ver?productId=SAS-48300&dn=Adaptec+Serial+Attached+SCSI+48300" and copy the BIOS image into /lib/firmware folder.
3. The aic994xx will accept "update bios_file" and "verify bios_file" commands to perform update and verify BIOS image .
For example:
Type "echo "update asc483c01.ufi" > /sys/devices/.../update_bios"
to update BIOS image from /lib/firmware/as483c01.ufi file into HBA's flash memory.
Type "echo "verify asc483c01.ufi" > /sys/devices/.../update_bios"
to verify BIOS image between /lib/firmware/asc48c01.ufi file and HBA's flash memory.
4. Type "cat /sys/devices/.../update_bios" to view the status or result of updating BIOS.
drivers/scsi/aic94xx/aic94xx_hwi.h +3 -0
@@ -72,6 +72,7 @@u8 manuf;u8 dev_id;u8 sec_prot; +u8 method;u32 dir_offs; };
@@ -216,6 +217,8 @@struct dma_pool *scb_pool;struct asd_seq_data seq;/* sequencer related */ +u32 bios_status; +const struct firmware *bios_image; };/* ---------- Common macros ---------- */
drivers/scsi/aic94xx/aic94xx_init.c +182 -0
220 lines not on this page · raw message
drivers/scsi/aic94xx/aic94xx_sds.c +441 -1
451 lines not on this page · raw message
drivers/scsi/aic94xx/aic94xx_sds.h +168 -0
168 lines not on this page · raw message
Quoted 6 lines · --- Gilbert Wu
1. Create a file "
update_bios" in sysfs to allow user to update bios from user space.2. The BIOS image file can be downloaded from web site
Quoted 211 lines
and copy the BIOS image into
/lib/firmwarefolder.3. The aic994xx will accept "update
bios_file" and "verifybios_file" commands to perform update and verify BIOS image .For example:
Type "echo "update asc483c01.ufi" >
/sys/devices/.../update_bios"
to update BIOS image from/lib/firmware/as483c01.ufifile into HBA's flash memory.Type "echo "verify asc483c01.ufi" >
/sys/devices/.../update_bios"
to verify BIOS image between/lib/firmware/asc48c01.ufifile and HBA's flash memory.4. Type "cat
/sys/devices/.../update_bios" to view the status or result of updating BIOS.Signed-off-by Gilbert Wu <[email protected]>diff -urN
a/drivers/scsi/aic94xx/aic94xx_hwi.hb/drivers/scsi/aic94xx/aic94xx_hwi.hdrivers/scsi/aic94xx/aic94xx_hwi.h +3
-0@@ -72,6 +72,7 @@u8 manuf;u8 dev_id;u8 sec_prot; +u8 method;u32 dir_offs; };@@ -216,6 +217,8 @@struct dma_pool *scb_pool;struct asd_seq_data seq;/* sequencer related */ +u32 bios_status; +const struct firmware *bios_image; };/* ---------- Common macros ---------- */ diff -urN
a/drivers/scsi/aic94xx/aic94xx_init.cb/drivers/scsi/aic94xx/aic94xx_init.cdrivers/scsi/aic94xx/aic94xx_init.c +146
-0@@ -29,6 +29,7 @@#include <linux/kernel.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/firmware.h> #include <scsi/scsi_host.h> @@ -36,6 +37,7 @@#include "aic94xx_reg.h" #include "aic94xx_hwi.h" #include "aic94xx_seq.h" +#include "aic94xx_sds.h" /* The format is "version.release.patchlevel" */ #define ASD_DRIVER_VERSION "1.0.3"@@ -313,6 +315,179 @@ } static DEVICE_ATTR(pcba_sn, S_IRUGO, asd_show_dev_pcba_sn, NULL); +#define FLASH_CMD_NONE 0x00 +#define FLASH_CMD_UPDATE 0x01 +#define FLASH_CMD_VERIFY 0x02 + +struct flash_command { +u8 command[8 ]; +int code; +}; + +static struct flash_command flash_command_table[] = +{ + {"verify" ,FLASH_CMD_VERIFY }, + {"update" ,FLASH_CMD_UPDATE }, + {"" ,FLASH_CMD_NONE }/* Last entry should be NULL. */ +}; + + +struct error_bios {char *reason;int err_code; +}; + +static struct error_bios flash_error_table[] = +{ + {"Failed to open bios image file" ,FAIL_OPEN_BIOS_FILE }, + {"PCI ID mismatch" ,FAIL_CHECK_PCI_ID }, + {"Checksum mismatch" ,FAIL_CHECK_SUM }, + {"Unknown Error" ,FAIL_UNKNOWN }, + {"Failed to verify." ,FAIL_VERIFY }, + {"Failed to reset flash chip." ,FAIL_RESET_FLASH }, + {"Failed to find flash chip type." ,FAIL_FIND_FLASH_ID }, + {"Failed to erash flash chip." ,FAIL_ERASE_FLASH }, + {"Failed to program flash chip." ,FAIL_WRITE_FLASH }, + {"Flash in progress" ,FLASH_IN_PROGRESS }, + {"Image file size Error" ,FAIL_FILE_SIZE }, + {"Input parameter error" ,FAIL_PARAMETERS }, + {"Out of memory" ,FAIL_OUT_MEMORY }, + {"OK" ,0 }/* Last entry err_code = 0. */ +}; + +static ssize_t asd_store_update_bios (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ +struct asd_ha_struct *asd_ha =dev_to_asd_ha (dev); +char *cmd_ptr,*filename_ptr; +struct bios_file_header header, *hdr_ptr; +int res,i; +u32 csum =0 ; +int flash_command =FLASH_CMD_NONE ; +int err =0 ; + + + cmd_ptr =kmalloc (count*2 ,GFP_KERNEL ); + +if (!cmd_ptr) { + err=FAIL_OUT_MEMORY ; + goto out; + } + +memset (cmd_ptr,0 ,count*2 ); + filename_ptr = cmd_ptr+count; + res =sscanf (buf,"%s %s" , cmd_ptr, filename_ptr); +if (res !=2 ) + { + err =FAIL_PARAMETERS ; + goto out1; + } + +for (i =0 ; flash_command_table[i].code !=FLASH_CMD_NONE ; i++) { +if (!memcmp (flash_command_table[i].command,cmd_ptr,strlen (cmd_ptr))) { + flash_command = flash_command_table[i].code; +break ; + } + } +if (flash_command ==FLASH_CMD_NONE ) { + err =FAIL_PARAMETERS ; + goto out1; + } + +if (asd_ha->bios_status ==FLASH_IN_PROGRESS ) { + err =FLASH_IN_PROGRESS ; + goto out1; + } + err =request_firmware (&asd_ha->bios_image, + filename_ptr, + &asd_ha->pcidev->dev); +if (err) { +asd_printk ("Failed to load bios image file %s, error %d\n" , + filename_ptr, err); + err =FAIL_OPEN_BIOS_FILE ; + goto out1; + } + + hdr_ptr = (struct bios_file_header *)asd_ha->bios_image->data; + +if ((hdr_ptr->contrl_id.vendor != asd_ha->pcidev->vendor || + hdr_ptr->contrl_id.device != asd_ha->pcidev->device) && + (hdr_ptr->contrl_id.sub_vendor != asd_ha->pcidev->vendor || + hdr_ptr->contrl_id.sub_device != asd_ha->pcidev->device)) { + +ASD_DPRINTK ("The PCI vendor id or device id does not match\n" ); +ASD_DPRINTK ("vendor=%x dev=%x sub_vendor=%x sub_dev=%x pci vendor=%x pci dev=%x \n" , + hdr_ptr->contrl_id.vendor, + hdr_ptr->contrl_id.device, + hdr_ptr->contrl_id.sub_vendor, + hdr_ptr->contrl_id.sub_device, + asd_ha->pcidev->vendor, + asd_ha->pcidev->device); + err =FAIL_CHECK_PCI_ID ; + goto out2; + } + +if (hdr_ptr->filelen != asd_ha->bios_image->size) { + err =FAIL_FILE_SIZE ; + goto out2; + } + +/* calculate checksum */ +for (i =0 ; i < hdr_ptr->filelen; i++) + csum += asd_ha->bios_image->data[i]; + +if ((csum &0x0000ffff ) != hdr_ptr->checksum) { +ASD_DPRINTK ("BIOS file checksum mismatch\n" ); + err =FAIL_CHECK_SUM ; + goto out2; + } +if (flash_command ==FLASH_CMD_UPDATE ) { + asd_ha->bios_status =FLASH_IN_PROGRESS ; + err =asd_write_flash_seg (asd_ha,&asd_ha->bios_image->data[sizeof (*hdr_ptr)] + ,0 ,hdr_ptr->filelen-sizeof (*hdr_ptr)); +if (!err) { + err =asd_verify_flash_seg (asd_ha,&asd_ha->bios_image->data[sizeof (*hdr_ptr)] + ,0 ,hdr_ptr->filelen-sizeof (*hdr_ptr)); + } + } +else { + asd_ha->bios_status =FLASH_IN_PROGRESS ; + err =asd_verify_flash_seg (asd_ha,&asd_ha->bios_image->data[sizeof (header)] + ,0 ,hdr_ptr->filelen-sizeof (header)); + } + +out2: +release_firmware (asd_ha->bios_image); +out1: +// free buffer +kfree (cmd_ptr);
drivers/scsi/aic94xx/aic94xx_init.c line 471
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_init.c +10
-0+out: + asd_ha->bios_status = err; + +if (!err) +return count; +else +return -err; + +} +static ssize_t asd_show_update_bios(struct device *dev,
Separate functions with an emtpy line, at least.
Quoted 104 lines
drivers/scsi/aic94xx/aic94xx_init.c +26
-0+ struct device_attribute *attr,char *buf) +{ + int i; +struct asd_ha_struct *asd_ha =dev_to_asd_ha (dev); +for (i =0 ; flash_error_table[i].err_code !=0 ; i++) { +if ( flash_error_table[i].err_code == asd_ha->bios_status) { +break ; + } + } +if (asd_ha->bios_status !=FLASH_IN_PROGRESS ) { + asd_ha->bios_status =FLASH_OK ; + } +return snprintf (buf,PAGE_SIZE ,"status=%x %s\n" , + flash_error_table[i].err_code, + flash_error_table[i].reason); +} + +static DEVICE_ATTR(update_bios, S_IRUGO|S_IWUGO,asd_show_update_bios,asd_store_update_bios); +static int asd_create_dev_attrs (struct asd_ha_struct *asd_ha) {int err;@@ -328,8 +503,13 @@ err =device_create_file (&asd_ha->pcidev->dev, &dev_attr_pcba_sn);if (err) goto err_biosb; + err =device_create_file (&asd_ha->pcidev->dev, &dev_attr_update_bios); +if (err) + goto err_update_bios;return 0 ; +err_update_bios: +device_remove_file (&asd_ha->pcidev->dev, &dev_attr_pcba_sn); err_biosb:device_remove_file (&asd_ha->pcidev->dev, &dev_attr_bios_build);@@ -343,6 +523,7 @@device_remove_file (&asd_ha->pcidev->dev, &dev_attr_revision);device_remove_file (&asd_ha->pcidev->dev, &dev_attr_bios_build);device_remove_file (&asd_ha->pcidev->dev, &dev_attr_pcba_sn); +device_remove_file (&asd_ha->pcidev->dev, &dev_attr_update_bios); }/* The first entry, 0, is used for dynamic ids, the rest for devices @@ -589,6 +770,7 @@ asd_ha->sas_ha.dev = &asd_ha->pcidev->dev; asd_ha->sas_ha.lldd_ha = asd_ha; + asd_ha->bios_status =FLASH_OK ; asd_ha->name = asd_dev->name;asd_printk ("found %s, device %s\n" , asd_ha->name,pci_name (dev));diff -urN
a/drivers/scsi/aic94xx/aic94xx_sds.cb/drivers/scsi/aic94xx/aic94xx_sds.cdrivers/scsi/aic94xx/aic94xx_sds.c +37
-1@@ -30,7 +30,7 @@#include "aic94xx.h" #include "aic94xx_reg.h" - +#include "aic94xx_sds.h" /* ---------- OCM stuff ---------- */ struct asd_ocm_dir_ent {@@ -1083,3 +1083,443 @@kfree (flash_dir);return err; } +/* +* Function: +* asd_hwi_write_nv_segment() +* +* Description: +* Writes data to an NVRAM segment. +*/ +int +asd_verify_flash_seg (struct asd_ha_struct *asd_ha, +void *src,u32 dest_offset,u32 bytes_to_verify) +{ +u8 *src_buf; +u8 flash_char; +int err; +u32 nv_offset, reg, i; + + + reg = asd_ha->hw_prof.flash.bar; + src_buf =NULL ; + + err =FLASH_OK ; + nv_offset = dest_offset; + src_buf = (u8 *)src; +for (i =0 ; i < bytes_to_verify; i++) { + + flash_char =asd_read_reg_byte (asd_ha,reg +nv_offset+i); +if (flash_char != src_buf[i]) { + err =FAIL_VERIFY ; +break ; + } + } +return (err); +} +/* +* Function: +* asd_hwi_write_nv_segment()
drivers/scsi/aic94xx/aic94xx_sds.c line 1131
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+* +* Description: +* Writes data to an NVRAM segment. +*/ +int +asd_write_flash_seg (struct asd_ha_struct *asd_ha, +void *src,u32 dest_offset,u32 bytes_to_write) +{ +u8 *src_buf; +u32 nv_offset, reg, i;
Space vs. tab formatting.
Quoted 34 lines
drivers/scsi/aic94xx/aic94xx_sds.c +34
-0+int err; + + + reg = asd_ha->hw_prof.flash.bar; + src_buf =NULL ; + + err =asd_check_flash_type (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't find the type of flah(%d)\n" , err); +return err; + } + + nv_offset = dest_offset; + err =asd_erase_nv_sector (asd_ha, nv_offset,bytes_to_write); +if (err) { +ASD_DPRINTK ("Erase failed at offset:0x%x\n" , + nv_offset); +return err; + } + + err =asd_reset_flash (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err); +return err; + } + + src_buf = (u8 *)src; +for (i =0 ; i < bytes_to_write; i++) { +/* Setup program command sequence */ +switch (asd_ha->hw_prof.flash.method) { +case FLASH_METHOD_A : + { + + asd_write_reg_byte(asd_ha,
drivers/scsi/aic94xx/aic94xx_sds.c line 1175
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ (reg + 0xAAA), 0xAA); +asd_write_reg_byte (asd_ha, + (reg +0x555 ),0x55 ); +asd_write_reg_byte (asd_ha, + (reg +0xAAA ),0xA0 ); +asd_write_reg_byte (asd_ha, + (reg + nv_offset + i), + (*(src_buf + i))); +break ; + }
You could also optimize "Method A" to write 2 bytes at a time, iff the flash is "wide".
Quoted 46 lines
drivers/scsi/aic94xx/aic94xx_sds.c +46
-0+case FLASH_METHOD_B : + { +asd_write_reg_byte (asd_ha, + (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, + (reg +0x2AA ),0x55 ); +asd_write_reg_byte (asd_ha, + (reg +0x555 ),0xA0 ); +asd_write_reg_byte (asd_ha, + (reg + nv_offset + i), + (*(src_buf + i))); +break ; + } +default : +break ; + } +if (asd_chk_write_status (asd_ha, (nv_offset + i), +0 /* WRITE operation */ ) !=0 ) { +ASD_DPRINTK ("aicx: Write failed at offset:0x%x\n" , + reg + nv_offset + i); +return FAIL_WRITE_FLASH ; + } + } + + err =asd_reset_flash (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err); +return err; + } +return (0 ); +} +int +asd_chk_write_status (struct asd_ha_struct *asd_ha,u32 sector_addr, +u8 erase_flag) +{ +u32 reg; +u32 loop_cnt; +u8 nv_data1, nv_data2; +u8 toggle_bit1/*, toggle_bit2*/ ; + +/* +* Read from DQ2 requires sector address +* while it's dont care for DQ6 +*/ +/* read_addr = asd->hw_prof.nv_flash_bar + sector_addr;*/ + reg = asd_ha->hw_prof.flash.bar;
drivers/scsi/aic94xx/aic94xx_sds.c line 1231
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ loop_cnt =50000 ; + +while (loop_cnt) { + nv_data1 =asd_read_reg_byte (asd_ha, reg); + nv_data2 =asd_read_reg_byte (asd_ha, reg); + + toggle_bit1 = ((nv_data1 &FLASH_STATUS_BIT_MASK_DQ6 ) + ^ (nv_data2 &FLASH_STATUS_BIT_MASK_DQ6 )); +/* toggle_bit2 = ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ2) +^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ2));*/
Hmm, I've found that using the "Poll program" sequence, using DQ7 (DATA#) and DQ5 (Timeout Status), to be much more reliable, as opposed to the toggle lines DQ6 and DQ2.
Quoted 29 lines
drivers/scsi/aic94xx/aic94xx_sds.c +29
-0+ +if (toggle_bit1 ==0 ) { +return (0 ); + }else { +if (nv_data2 &FLASH_STATUS_BIT_MASK_DQ5 ) { + nv_data1 =asd_read_reg_byte (asd_ha, + reg); + nv_data2 =asd_read_reg_byte (asd_ha, + reg); + toggle_bit1 = + ((nv_data1 &FLASH_STATUS_BIT_MASK_DQ6 ) + ^ (nv_data2 &FLASH_STATUS_BIT_MASK_DQ6 )); +/* +toggle_bit2 = +((nv_data1 & FLASH_STATUS_BIT_MASK_DQ2) +^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ2)); +*/ +if (toggle_bit1 ==0 ) { +return 0 ; + } + } + } + loop_cnt--; + +/* +* ERASE is a sector-by-sector operation and requires +* more time to finish while WRITE is byte-byte-byte +* operation and takes lesser time to finish. +*
drivers/scsi/aic94xx/aic94xx_sds.c line 1270
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+* For some strange reason a reduced ERASE delay gives different +* behaviour across different spirit boards. Hence we set +* a optimum balance of 50mus for ERASE which works well +* across all boards. +*/ +if (erase_flag) { +udelay (FLASH_STATUS_ERASE_DELAY_COUNT ); + }else { +udelay (FLASH_STATUS_WRITE_DELAY_COUNT ); + }
Sometimes this isn't enough and when writing large contents, say 4 or 8 MB you need something like the following:
if (need_resched()) schedule_timeout_interruptible(HZ); else udelay(10); if (signal_pending(current)) return -EINTR;
Else the rest of the system becomes unresponsive and slow due to the "busy" (and long for large firmware) "udelay".
Quoted 100 lines
drivers/scsi/aic94xx/aic94xx_sds.c +99
-0+ } +return (-1 ); +} +/* +* Function: +* asd_hwi_erase_nv_sector() +* +* Description: +* Erase the requested NVRAM sector. +*/ +int +asd_erase_nv_sector (struct asd_ha_struct *asd_ha,u32 flash_addr,u32 size) +{ +u32 reg; +u32 sector_addr; + reg = asd_ha->hw_prof.flash.bar; +/* sector staring address */ + sector_addr = flash_addr &FLASH_SECTOR_SIZE_MASK ; +/* +* Erasing an NVRAM sector needs to be done in six consecutive +* write cyles. +*/ +while (sector_addr < flash_addr+size) { +switch (asd_ha->hw_prof.flash.method) { + +case FLASH_METHOD_A : +asd_write_reg_byte (asd_ha, (reg +0xAAA ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x55 ); +asd_write_reg_byte (asd_ha, (reg +0xAAA ),0x80 ); +asd_write_reg_byte (asd_ha, (reg +0xAAA ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x55 ); +asd_write_reg_byte (asd_ha, (reg + sector_addr),0x30 ); +break ; + +case FLASH_METHOD_B : +asd_write_reg_byte (asd_ha, (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x2AA ),0x55 ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x80 ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x2AA ),0x55 ); +asd_write_reg_byte (asd_ha, (reg + sector_addr),0x30 ); +break ; + +default : +break ; + } + +if (asd_chk_write_status (asd_ha, sector_addr, +1 /* ERASE operation */ ) !=0 ) { +return FAIL_ERASE_FLASH ; + } + + sector_addr +=FLASH_SECTOR_SIZE ; + } + +return (0 ); +} +int asd_check_flash_type (struct asd_ha_struct *asd_ha) +{ +u8 manuf_id; +u8 dev_id; +u8 sec_prot; +u32 inc; +u32 reg; +int err; + +/* get Flash memory base address */ + reg = asd_ha->hw_prof.flash.bar; + + +/* Determine flash info */ + err =asd_reset_flash (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err); +return (err); + } + + asd_ha->hw_prof.flash.method =FLASH_METHOD_UNKNOWN ; + asd_ha->hw_prof.flash.manuf =FLASH_MANUF_ID_UNKNOWN ; + asd_ha->hw_prof.flash.dev_id =FLASH_DEV_ID_UNKNOWN ; + +/* Get flash info. This would most likely be AMD Am29LV family flash. +* First try the sequence for word mode. It is the same as for +* 008B (byte mode only), 160B (word mode) and 800D (word mode). +*/ + inc = asd_ha->hw_prof.flash.wide ?2 :1 ; +asd_write_reg_byte (asd_ha, reg +0xAAA ,0xAA ); +asd_write_reg_byte (asd_ha, reg +0x555 ,0x55 ); +asd_write_reg_byte (asd_ha, reg +0xAAA ,0x90 ); + manuf_id =asd_read_reg_byte (asd_ha, reg); + dev_id =asd_read_reg_byte (asd_ha,reg+inc); + sec_prot =asd_read_reg_byte (asd_ha,reg+inc+inc); +/* Get out of autoselect mode. */ + err =asd_reset_flash (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err); +return err; + } + ASD_DPRINTK("Flash MethodA manuf_id(0x%x) dev_id(0x%x)sec_prot(0x%x)\n",manuf_id,dev_id,sec_prot);
drivers/scsi/aic94xx/aic94xx_sds.c line 1375
Quoted 6 lines
drivers/scsi/aic94xx/aic94xx_sds.c +6
-0+ err =asd_reset_flash (asd_ha); +if (err !=0 ) { +return (err); + } + +switch (manuf_id) {
Ouch! The flash access method doesn't depend on the manufacturer, but on the width of the flash and on the way it is actually connected to the EXSI block, although an 8 bit flash could be connected in only one way, 16 bit flash could be connected in 8 or 16 bit way. Take a look at the schematic and work out what goes out XADDRx and into Ax for each sequence and you'll see it.
Luben
Quoted 329 lines
drivers/scsi/aic94xx/aic94xx_sds.c +71
-0+ +case FLASH_MANUF_ID_AMD : + +switch (sec_prot) { + +case FLASH_DEV_ID_AM29LV800DT : +case FLASH_DEV_ID_AM29LV640MT : +case FLASH_DEV_ID_AM29F800B : + asd_ha->hw_prof.flash.method =FLASH_METHOD_A ; +break ; +default : +break ; + } +break ; + +case FLASH_MANUF_ID_ST : + +switch (sec_prot) { + +case FLASH_DEV_ID_STM29W800DT : +case FLASH_DEV_ID_STM29LV640 : + asd_ha->hw_prof.flash.method =FLASH_METHOD_A ; +break ; +default : +break ; + } +break ; + +case FLASH_MANUF_ID_FUJITSU : + +switch (sec_prot) { + +case FLASH_DEV_ID_MBM29LV800TE : +case FLASH_DEV_ID_MBM29DL800TA : + asd_ha->hw_prof.flash.method =FLASH_METHOD_A ; +break ; + + } +break ; + +case FLASH_MANUF_ID_MACRONIX : + +switch (sec_prot) { + +case FLASH_DEV_ID_MX29LV800BT : + asd_ha->hw_prof.flash.method =FLASH_METHOD_A ; +break ; + } +break ; + } + +if (asd_ha->hw_prof.flash.method ==FLASH_METHOD_UNKNOWN ) { + + err =asd_reset_flash (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err); +return err; + } + +/* Issue Unlock sequence for AM29LV008BT */ +asd_write_reg_byte (asd_ha, (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x2AA ),0x55 ); + +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x90 ); + + manuf_id =asd_read_reg_byte (asd_ha, reg); + dev_id =asd_read_reg_byte (asd_ha, reg + inc); + sec_prot =asd_read_reg_byte (asd_ha, reg + inc+inc); + + + ASD_DPRINTK("Flash MethodB manuf_id(0x%x) dev_id(0x%x)sec_prot(0x%x)\n",manuf_id,dev_id,sec_prot);
drivers/scsi/aic94xx/aic94xx_sds.c +79
-0+ + err =asd_reset_flash (asd_ha); +if (err !=0 ) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err); +return (err); + } + +switch (manuf_id) { +case FLASH_MANUF_ID_AMD : + +switch (dev_id) { + +case FLASH_DEV_ID_AM29LV008BT : + asd_ha->hw_prof.flash.method =FLASH_METHOD_B ; +break ; +default : +break ; + } +break ; + +case FLASH_MANUF_ID_ST : + +switch (dev_id) { + +case FLASH_DEV_ID_STM29008 : + asd_ha->hw_prof.flash.method =FLASH_METHOD_B ; +break ; +default : +break ; + } +break ; + +case FLASH_MANUF_ID_FUJITSU : + +switch (dev_id) { + +case FLASH_DEV_ID_MBM29LV008TA : + asd_ha->hw_prof.flash.method =FLASH_METHOD_B ; +break ; + + } +break ; + +case FLASH_MANUF_ID_INTEL : + +switch (dev_id) { + +case FLASH_DEV_ID_I28LV00TAT : + asd_ha->hw_prof.flash.method =FLASH_METHOD_B ; +break ; + + } +break ; + +case FLASH_MANUF_ID_MACRONIX : + +switch (dev_id) { + +case FLASH_DEV_ID_I28LV00TAT : + asd_ha->hw_prof.flash.method =FLASH_METHOD_B ; +break ; + + } +break ; + +default : +return FAIL_FIND_FLASH_ID ; + } + } + +if (asd_ha->hw_prof.flash.method ==FLASH_METHOD_UNKNOWN ) +return FAIL_FIND_FLASH_ID ; + + + asd_ha->hw_prof.flash.manuf = manuf_id; + asd_ha->hw_prof.flash.dev_id = dev_id; + asd_ha->hw_prof.flash.sec_prot = sec_prot; +return 0 ; +}diff -urN
a/drivers/scsi/aic94xx/aic94xx_sds.hb/drivers/scsi/aic94xx/aic94xx_sds.hdrivers/scsi/aic94xx/aic94xx_sds.h +168
-1@@ -0,0 +1,168 @@ +/* +* Aic94xx SAS/SATA driver hardware interface header file. +* +* Copyright (C) 2005 Adaptec, Inc. All rights reserved. +* Copyright (C) 2005 Gilbert Wu <[email protected]> +* +* This file is licensed under GPLv2. +* +* This file is part of the aic94xx driver. +* +* The aic94xx driver 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. +* +* The aic94xx driver 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 the aic94xx driver; if not, write to the Free Software +* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +* +*/ +#ifndef _AIC94XX_SDS_H_ +#define _AIC94XX_SDS_H_ + +enum { +FLASH_METHOD_UNKNOWN , +FLASH_METHOD_A , +FLASH_METHOD_B +}; + +#define FLASH_MANUF_ID_AMD 0x01 +#define FLASH_MANUF_ID_ST 0x20 +#define FLASH_MANUF_ID_FUJITSU 0x04 +#define FLASH_MANUF_ID_MACRONIX 0xC2 +#define FLASH_MANUF_ID_INTEL 0x89 +#define FLASH_MANUF_ID_UNKNOWN 0xFF + +#define FLASH_DEV_ID_AM29LV008BT 0x3E +#define FLASH_DEV_ID_AM29LV800DT 0xDA +#define FLASH_DEV_ID_STM29W800DT 0xD7 +#define FLASH_DEV_ID_STM29LV640 0xDE +#define FLASH_DEV_ID_STM29008 0xEA +#define FLASH_DEV_ID_MBM29LV800TE 0xDA +#define FLASH_DEV_ID_MBM29DL800TA 0x4A +#define FLASH_DEV_ID_MBM29LV008TA 0x3E +#define FLASH_DEV_ID_AM29LV640MT 0x7E +#define FLASH_DEV_ID_AM29F800B 0xD6 +#define FLASH_DEV_ID_MX29LV800BT 0xDA +#define FLASH_DEV_ID_MX29LV008CT 0xDA +#define FLASH_DEV_ID_I28LV00TAT 0x3E +#define FLASH_DEV_ID_UNKNOWN 0xFF +/* status bit mask values */ +#define FLASH_STATUS_BIT_MASK_DQ6 0x40 +#define FLASH_STATUS_BIT_MASK_DQ5 0x20 +#define FLASH_STATUS_BIT_MASK_DQ2 0x04 +/* minimum value in micro seconds needed for checking status */ +#define FLASH_STATUS_ERASE_DELAY_COUNT 50 +#define FLASH_STATUS_WRITE_DELAY_COUNT 25 + +#define FLASH_SECTOR_SIZE 0x010000 +#define FLASH_SECTOR_SIZE_MASK 0xffff0000 + + + +#define FLASH_OK 0x000000 +#define FAIL_OPEN_BIOS_FILE 0x000100 +#define FAIL_CHECK_PCI_ID 0x000200 +#define FAIL_CHECK_SUM 0x000300 +#define FAIL_UNKNOWN 0x000400 +#define FAIL_VERIFY 0x000500 +#define FAIL_RESET_FLASH 0x000600 +#define FAIL_FIND_FLASH_ID 0x000700 +#define FAIL_ERASE_FLASH 0x000800 +#define FAIL_WRITE_FLASH 0x000900 +#define FAIL_FILE_SIZE 0x000a00 +#define FAIL_PARAMETERS 0x000b00 +#define FAIL_OUT_MEMORY 0x000c00 +#define FLASH_IN_PROGRESS 0x001000 + + +struct controller_id +{ +u32 vendor; +/* PCI Vendor ID */ + +u32 device; +/* PCI Device ID */ + +u32 sub_vendor; +/* PCI Subvendor ID */ + +u32 sub_device; +/* PCI Subdevice ID */ + +}; +struct image_info +{ +u32 ImageId; +/*Identifies the image(e.g 0=Footbridge image,1=Drawbridge image)*/ + +u32 ImageOffset; +/*Offset of the image from the beginning of the file*/ + +u32 ImageLength; +/*length of the image*/ + +u32 ImageChecksum; +/*Image checksum*/ + +u32 ImageVersion; +/*Version of the image, could be build number*/ +}; + +struct bios_file_header +{ +u8 signature[32 ]; +/* Signature/Cookie to identify the file*/ +/* The signature above is only 25 characters long. The program will insert a +Build Number and a ^Z to the end of the string, so that a user can issue the +DOS type command against the file and have the signature displayed to identify +the file. */ + +u32 checksum; +/*Entire file checksum with this field zero*/ + +u32 antidote; +/*Entire file checksum antidote with this field 0xFFFFFFFF*/ + +struct controller_id contrl_id; +/*Controller id to identify the controller whose images are*/ +/*stored in the file. */ + +u32 filelen; +/*Length of the entire file*/ + +u32 chunk_num; +/*The chunk/part number of this DOS file in case the Image */ +/*is stored in parts in multiple DOS files across floppies*/ + +u32 total_chunks; +/*Total number of chunks/parts in which the image file is stored*/ + +u32 num_images; +/*Number of images in the file,e.g Footbridge image, Drawbridge image*/ + +u32 build_num; +/*Build number of the process that generated this image*/ + +struct image_info image_header; +}; + +int asd_verify_flash_seg (struct asd_ha_struct *asd_ha, +void *src,u32 dest_offset,u32 bytes_to_verify); +int asd_write_flash_seg (struct asd_ha_struct *asd_ha, +void *src,u32 dest_offset,u32 bytes_to_write); +int asd_chk_write_status (struct asd_ha_struct *asd_ha, +u32 sector_addr,u8 erase_flag); +int asd_check_flash_type (struct asd_ha_struct *asd_ha); +int asd_erase_nv_sector (struct asd_ha_struct *asd_ha,u32 flash_addr,u32 size); +#endif + + + + -To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 57 lines · Gilbert Wu
diff -urN
a/drivers/scsi/aic94xx/aic94xx_init.cb/drivers/scsi/aic94xx/aic94xx_init.c---a/drivers/scsi/aic94xx/aic94xx_init.c2007-10-10 17:13:29.000000000 -0700
+++b/drivers/scsi/aic94xx/aic94xx_init.c2007-10-10 17:15:58.000000000
-0700drivers/scsi/aic94xx/aic94xx_init.c +47
-0@@ -313,6 +315,179 @@ } static DEVICE_ATTR(pcba_sn, S_IRUGO, asd_show_dev_pcba_sn, NULL); +#define FLASH_CMD_NONE 0x00 +#define FLASH_CMD_UPDATE 0x01 +#define FLASH_CMD_VERIFY 0x02 + +struct flash_command { +u8 command[8 ]; +int code; +}; + +static struct flash_command flash_command_table[] = +{ + {"verify" ,FLASH_CMD_VERIFY }, + {"update" ,FLASH_CMD_UPDATE }, + {"" ,FLASH_CMD_NONE }/* Last entry should be NULL. */ +}; + + +struct error_bios {char *reason;int err_code; +}; + +static struct error_bios flash_error_table[] = +{ + {"Failed to open bios image file" ,FAIL_OPEN_BIOS_FILE }, + {"PCI ID mismatch" ,FAIL_CHECK_PCI_ID }, + {"Checksum mismatch" ,FAIL_CHECK_SUM }, + {"Unknown Error" ,FAIL_UNKNOWN }, + {"Failed to verify." ,FAIL_VERIFY }, + {"Failed to reset flash chip." ,FAIL_RESET_FLASH }, + {"Failed to find flash chip type." ,FAIL_FIND_FLASH_ID }, + {"Failed to erash flash chip." ,FAIL_ERASE_FLASH }, + {"Failed to program flash chip." ,FAIL_WRITE_FLASH }, + {"Flash in progress" ,FLASH_IN_PROGRESS }, + {"Image file size Error" ,FAIL_FILE_SIZE }, + {"Input parameter error" ,FAIL_PARAMETERS }, + {"Out of memory" ,FAIL_OUT_MEMORY }, + {"OK" ,0 }/* Last entry err_code = 0. */ +}; + +static ssize_t asd_store_update_bios (struct device *dev,struct device_attribute *attr, + const char *buf, size_t count) +{ +struct asd_ha_struct *asd_ha =dev_to_asd_ha (dev); +char *cmd_ptr,*filename_ptr; +struct bios_file_header header, *hdr_ptr; +int res,i; +u32 csum =0 ; +int flash_command =FLASH_CMD_NONE ; +int err =0 ;
drivers/scsi/aic94xx/aic94xx_init.c line 375
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_init.c +10
-0+ + + cmd_ptr =kmalloc (count*2 ,GFP_KERNEL ); + +if (!cmd_ptr) { + err=FAIL_OUT_MEMORY ; + goto out; + } + +memset (cmd_ptr,0 ,count*2 );
cmd_ptr = kzalloc(count * 2, GFP_KERNEL);
drivers/scsi/aic94xx/aic94xx_init.c line 385
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_init.c +10
-0+ filename_ptr = cmd_ptr+count; + res =sscanf (buf,"%s %s" , cmd_ptr, filename_ptr); +if (res !=2 ) + { + err =FAIL_PARAMETERS ; + goto out1; + } + +for (i =0 ; flash_command_table[i].code !=FLASH_CMD_NONE ; i++) { +if (!memcmp (flash_command_table[i].command,cmd_ptr,strlen (cmd_ptr))) {
^
Space missing
Quoted 23 lines
drivers/scsi/aic94xx/aic94xx_init.c +23
-0+ flash_command = flash_command_table[i].code; +break ; + } + } +if (flash_command ==FLASH_CMD_NONE ) { + err =FAIL_PARAMETERS ; + goto out1; + } + +if (asd_ha->bios_status ==FLASH_IN_PROGRESS ) { + err =FLASH_IN_PROGRESS ; + goto out1; + } + err =request_firmware (&asd_ha->bios_image, + filename_ptr, + &asd_ha->pcidev->dev); +if (err) { +asd_printk ("Failed to load bios image file %s, error %d\n" , + filename_ptr, err); + err =FAIL_OPEN_BIOS_FILE ; + goto out1; + } +
drivers/scsi/aic94xx/aic94xx_init.c
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_init.c +9
-0+ hdr_ptr = (struct bios_file_header *)asd_ha->bios_image->data; + +if ((hdr_ptr->contrl_id.vendor != asd_ha->pcidev->vendor || + hdr_ptr->contrl_id.device != asd_ha->pcidev->device) && + (hdr_ptr->contrl_id.sub_vendor != asd_ha->pcidev->vendor || + hdr_ptr->contrl_id.sub_device != asd_ha->pcidev->device)) { + +ASD_DPRINTK ("The PCI vendor id or device id does not match\n" ); + ASD_DPRINTK("vendor=%x dev=%x sub_vendor=%x sub_dev=%x pci vendor=%x pci dev=%x \n", + hdr_ptr->contrl_id.vendor,
^
Superfluous whitespace
Quoted 27 lines
drivers/scsi/aic94xx/aic94xx_init.c +26
-0+ hdr_ptr->contrl_id.device, + hdr_ptr->contrl_id.sub_vendor, + hdr_ptr->contrl_id.sub_device, + asd_ha->pcidev->vendor, + asd_ha->pcidev->device); + err =FAIL_CHECK_PCI_ID ; + goto out2; + } + +if (hdr_ptr->filelen != asd_ha->bios_image->size) { + err =FAIL_FILE_SIZE ; + goto out2; + } + +/* calculate checksum */ +for (i =0 ; i < hdr_ptr->filelen; i++) + csum += asd_ha->bios_image->data[i]; + +if ((csum &0x0000ffff ) != hdr_ptr->checksum) { +ASD_DPRINTK ("BIOS file checksum mismatch\n" ); + err =FAIL_CHECK_SUM ; + goto out2; + } +if (flash_command ==FLASH_CMD_UPDATE ) { + asd_ha->bios_status =FLASH_IN_PROGRESS ; + err =asd_write_flash_seg(asd_ha,&asd_ha->bios_image->data[sizeof(*hdr_ptr)]
Review
Quoted 1 line
(quoted diff) +1
-0+ ,0,hdr_ptr->filelen-sizeof(*hdr_ptr));
^
This comma belongs in the last line.
Review
Quoted 4 lines
(quoted diff) +2
-0+ if (!err) { + err =asd_verify_flash_seg(asd_ha,&asd_ha->bios_image->data[sizeof(*hdr_ptr)]
(quoted diff) +1
-0+ ,0,hdr_ptr->filelen-sizeof(*hdr_ptr));
^
This one too.
drivers/scsi/aic94xx/aic94xx_init.c line 460
Quoted 13 lines
drivers/scsi/aic94xx/aic94xx_init.c +5
-0+ } + } +else { + asd_ha->bios_status =FLASH_IN_PROGRESS ; + err =asd_verify_flash_seg(asd_ha,&asd_ha->bios_image->data[sizeof(header)]
drivers/scsi/aic94xx/aic94xx_init.c +7
-0+ ,0,hdr_ptr->filelen-sizeof(header)); + } + +out2: +release_firmware (asd_ha->bios_image); +out1: +// free buffer
It's rather obvious what kfree() does, isn't it?
drivers/scsi/aic94xx/aic94xx_sds.c line 33
Quoted 10 lines
diff -urN
a/drivers/scsi/aic94xx/aic94xx_sds.cb/drivers/scsi/aic94xx/aic94xx_sds.c---a/drivers/scsi/aic94xx/aic94xx_sds.c2007-10-10 17:13:43.000000000 -0700
+++b/drivers/scsi/aic94xx/aic94xx_sds.c2007-10-10 17:16:10.000000000
-0700 @@ -30,7 +30,7 @@#include "
aic94xx.h"
#include "aic94xx_reg.h"drivers/scsi/aic94xx/aic94xx_sds.c +1
-1- +#include "aic94xx_sds.h"
I prefer a newline before this comment. YMMV.
Quoted 4 lines
/* ---------- OCM stuff ---------- */
struct
asd_ocm_dir_ent{
drivers/scsi/aic94xx/aic94xx_sds.c line 1092
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +7
-0@@ -1083,3 +1083,443 @@kfree (flash_dir);return err; } +/* +* Function: +* asd_hwi_write_nv_segment() +* +* Description: +* Writes data to an NVRAM segment. +*/
Kernel-doc description?
/**
* asd_hwi_write_nv_segment - Writes data to an NVRAM segment
* @asd_ha: ...
Quoted 15 lines
drivers/scsi/aic94xx/aic94xx_sds.c +15
-0+int +asd_verify_flash_seg (struct asd_ha_struct *asd_ha, +void *src,u32 dest_offset,u32 bytes_to_verify) +{ +u8 *src_buf; +u8 flash_char; +int err; +u32 nv_offset, reg, i; + + + reg = asd_ha->hw_prof.flash.bar; + src_buf =NULL ; + + err =FLASH_OK ; + nv_offset = dest_offset;
drivers/scsi/aic94xx/aic94xx_sds.c line 1117
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ src_buf = (u8 *)src; +for (i =0 ; i < bytes_to_verify; i++) { + + flash_char =asd_read_reg_byte (asd_ha,reg +nv_offset+i); +if (flash_char != src_buf[i]) { + err =FAIL_VERIFY ; +break ; + } + } +return (err);
return err;
Quoted 13 lines
drivers/scsi/aic94xx/aic94xx_sds.c +13
-0+} +/* +* Function: +* asd_hwi_write_nv_segment() +* +* Description: +* Writes data to an NVRAM segment. +*/ +int +asd_write_flash_seg (struct asd_ha_struct *asd_ha, +void *src,u32 dest_offset,u32 bytes_to_write) +{ +u8 *src_buf;
drivers/scsi/aic94xx/aic94xx_sds.c line 1140
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+u32 nv_offset, reg, i; +int err; + + + reg = asd_ha->hw_prof.flash.bar; + src_buf =NULL ; + + err =asd_check_flash_type (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't find the type of flah(%d)\n" , err);
^^
flash, I'd prefer whitespace before the number. In this form someone could think it's a flash index and not the error code on the first look.
Quoted 4 lines
drivers/scsi/aic94xx/aic94xx_sds.c +4
-0+return err; + } + + nv_offset = dest_offset;
drivers/scsi/aic94xx/aic94xx_sds.c line 1154
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ err =asd_erase_nv_sector (asd_ha, nv_offset,bytes_to_write); +if (err) { +ASD_DPRINTK ("Erase failed at offset:0x%x\n" , + nv_offset); +return err; + } + + err =asd_reset_flash (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err);
^
Whitespace, too.
Quoted 29 lines
drivers/scsi/aic94xx/aic94xx_sds.c +29
-0+return err; + } + + src_buf = (u8 *)src; +for (i =0 ; i < bytes_to_write; i++) { +/* Setup program command sequence */ +switch (asd_ha->hw_prof.flash.method) { +case FLASH_METHOD_A : + { + +asd_write_reg_byte (asd_ha, + (reg +0xAAA ),0xAA ); +asd_write_reg_byte (asd_ha, + (reg +0x555 ),0x55 ); +asd_write_reg_byte (asd_ha, + (reg +0xAAA ),0xA0 ); +asd_write_reg_byte (asd_ha, + (reg + nv_offset + i), + (*(src_buf + i))); +break ; + } +case FLASH_METHOD_B : + { +asd_write_reg_byte (asd_ha, + (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, + (reg +0x2AA ),0x55 ); +asd_write_reg_byte (asd_ha, + (reg +0x555 ),0xA0 );
drivers/scsi/aic94xx/aic94xx_sds.c line 1193
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+asd_write_reg_byte (asd_ha, + (reg + nv_offset + i), + (*(src_buf + i))); +break ; + } +default : +break ; + } +if (asd_chk_write_status (asd_ha, (nv_offset + i), +0 /* WRITE operation */ ) !=0 ) {
Putting the comment on an own line would make it more readable IMHO.
Quoted 4 lines
drivers/scsi/aic94xx/aic94xx_sds.c +4
-0+ASD_DPRINTK ("aicx: Write failed at offset:0x%x\n" , + reg + nv_offset + i); +return FAIL_WRITE_FLASH ; + }
drivers/scsi/aic94xx/aic94xx_sds.c line 1207
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ } + + err =asd_reset_flash (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err); +return err; + } +return (0 ); +} +int
Empty line between functions missing. More of this on other places.
Quoted 7 lines
drivers/scsi/aic94xx/aic94xx_sds.c +7
-0+asd_chk_write_status(struct asd_ha_struct *asd_ha, u32 sector_addr, + u8 erase_flag) +{ + u32 reg; +u32 loop_cnt; +u8 nv_data1, nv_data2; +u8 toggle_bit1/*, toggle_bit2*/ ;
drivers/scsi/aic94xx/aic94xx_sds.c line 1224
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ +/* +* Read from DQ2 requires sector address +* while it's dont care for DQ6 +*/ +/* read_addr = asd->hw_prof.nv_flash_bar + sector_addr;*/ + reg = asd_ha->hw_prof.flash.bar; + loop_cnt =50000 ; + +while (loop_cnt) {
for-loop?
drivers/scsi/aic94xx/aic94xx_sds.c line 1234
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ nv_data1 =asd_read_reg_byte (asd_ha, reg); + nv_data2 =asd_read_reg_byte (asd_ha, reg); + + toggle_bit1 = ((nv_data1 &FLASH_STATUS_BIT_MASK_DQ6 ) + ^ (nv_data2 &FLASH_STATUS_BIT_MASK_DQ6 )); +/* toggle_bit2 = ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ2) +^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ2));*/ + +if (toggle_bit1 ==0 ) { +return (0 );
return 0;
Quoted 28 lines
drivers/scsi/aic94xx/aic94xx_sds.c +28
-0+ }else { +if (nv_data2 &FLASH_STATUS_BIT_MASK_DQ5 ) { + nv_data1 =asd_read_reg_byte (asd_ha, + reg); + nv_data2 =asd_read_reg_byte (asd_ha, + reg); + toggle_bit1 = + ((nv_data1 &FLASH_STATUS_BIT_MASK_DQ6 ) + ^ (nv_data2 &FLASH_STATUS_BIT_MASK_DQ6 )); +/* +toggle_bit2 = +((nv_data1 & FLASH_STATUS_BIT_MASK_DQ2) +^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ2)); +*/ +if (toggle_bit1 ==0 ) { +return 0 ; + } + } + } + loop_cnt--; + +/* +* ERASE is a sector-by-sector operation and requires +* more time to finish while WRITE is byte-byte-byte +* operation and takes lesser time to finish. +* +* For some strange reason a reduced ERASE delay gives different +* behaviour across different spirit boards. Hence we set
drivers/scsi/aic94xx/aic94xx_sds.c line 1272
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+* a optimum balance of 50mus for ERASE which works well +* across all boards. +*/ +if (erase_flag) { +udelay (FLASH_STATUS_ERASE_DELAY_COUNT ); + }else { +udelay (FLASH_STATUS_WRITE_DELAY_COUNT ); + } + } +return (-1 );
return -1;
drivers/scsi/aic94xx/aic94xx_sds.c line 1280
Quoted 8 lines
drivers/scsi/aic94xx/aic94xx_sds.c +8
-0+} +/* +* Function: +* asd_hwi_erase_nv_sector() +* +* Description: +* Erase the requested NVRAM sector. +*/
Kerneldoc again?
Quoted 36 lines
drivers/scsi/aic94xx/aic94xx_sds.c +36
-0+int +asd_erase_nv_sector (struct asd_ha_struct *asd_ha,u32 flash_addr,u32 size) +{ +u32 reg; +u32 sector_addr; + reg = asd_ha->hw_prof.flash.bar; +/* sector staring address */ + sector_addr = flash_addr &FLASH_SECTOR_SIZE_MASK ; +/* +* Erasing an NVRAM sector needs to be done in six consecutive +* write cyles. +*/ +while (sector_addr < flash_addr+size) { +switch (asd_ha->hw_prof.flash.method) { + +case FLASH_METHOD_A : +asd_write_reg_byte (asd_ha, (reg +0xAAA ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x55 ); +asd_write_reg_byte (asd_ha, (reg +0xAAA ),0x80 ); +asd_write_reg_byte (asd_ha, (reg +0xAAA ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x55 ); +asd_write_reg_byte (asd_ha, (reg + sector_addr),0x30 ); +break ; + +case FLASH_METHOD_B : +asd_write_reg_byte (asd_ha, (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x2AA ),0x55 ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x80 ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x2AA ),0x55 ); +asd_write_reg_byte (asd_ha, (reg + sector_addr),0x30 ); +break ; + +default : +break ; + }
drivers/scsi/aic94xx/aic94xx_sds.c line 1326
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ +if (asd_chk_write_status (asd_ha, sector_addr, +1 /* ERASE operation */ ) !=0 ) { +return FAIL_ERASE_FLASH ; + } + + sector_addr +=FLASH_SECTOR_SIZE ; + } + +return (0 );
return 0;
Greetings,
Eike
Hi Eike,
Thanks! I will correct it.
Gilbert
-----Original Message-----
From: Rolf Eike Beer [mailto:[email protected]]
Sent: Thursday, October 11, 2007 12:47 AM
To: Wu, Gilbert
Cc: [email protected]
Subject: Re: [PATCH] aic94xx: update BIOS image from user space.
Quoted 3 lines · Gilbert Wu
diff -urN
a/drivers/scsi/aic94xx/aic94xx_init.cb/drivers/scsi/aic94xx/aic94xx_init.c---a/drivers/scsi/aic94xx/aic94xx_init.c2007-10-10 17:13:29.000000000
-0700
Quoted 1 line
+++
b/drivers/scsi/aic94xx/aic94xx_init.c2007-10-10
17:15:58.000000000
Quoted 9 lines
-0700
drivers/scsi/aic94xx/aic94xx_init.c +4
-0@@ -313,6 +315,179 @@ } static DEVICE_ATTR(pcba_sn, S_IRUGO, asd_show_dev_pcba_sn, NULL); +#define FLASH_CMD_NONE 0x00 +#define FLASH_CMD_UPDATE 0x01 +#define FLASH_CMD_VERIFY 0x02 +
drivers/scsi/aic94xx/aic94xx_init.c line 331
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_init.c +10
-0+struct flash_command { +u8 command[8 ]; +int code; +}; + +static struct flash_command flash_command_table[] = +{ + {"verify" ,FLASH_CMD_VERIFY }, + {"update" ,FLASH_CMD_UPDATE }, + {"" ,FLASH_CMD_NONE }/* Last entry should be
NULL. */
Quoted 25 lines
drivers/scsi/aic94xx/aic94xx_init.c +25
-0+}; + + +struct error_bios {char *reason;int err_code; +}; + +static struct error_bios flash_error_table[] = +{ + {"Failed to open bios image file" ,FAIL_OPEN_BIOS_FILE }, + {"PCI ID mismatch" ,FAIL_CHECK_PCI_ID }, + {"Checksum mismatch" ,FAIL_CHECK_SUM }, + {"Unknown Error" ,FAIL_UNKNOWN }, + {"Failed to verify." ,FAIL_VERIFY }, + {"Failed to reset flash chip." ,FAIL_RESET_FLASH }, + {"Failed to find flash chip type." ,FAIL_FIND_FLASH_ID }, + {"Failed to erash flash chip." ,FAIL_ERASE_FLASH }, + {"Failed to program flash chip." ,FAIL_WRITE_FLASH }, + {"Flash in progress" ,FLASH_IN_PROGRESS }, + {"Image file size Error" ,FAIL_FILE_SIZE }, + {"Input parameter error" ,FAIL_PARAMETERS }, + {"Out of memory" ,FAIL_OUT_MEMORY }, + {"OK" ,0 }/* Last entry err_code = 0. */ +}; + +static ssize_t asd_store_update_bios(struct device *dev,struct
Quoted 1 line
device_attribute*attr, + const char
*buf, size_t count)
Quoted 8 lines
drivers/scsi/aic94xx/aic94xx_init.c +8
-0+{ +struct asd_ha_struct *asd_ha =dev_to_asd_ha (dev); +char *cmd_ptr,*filename_ptr; +struct bios_file_header header, *hdr_ptr; +int res,i; +u32 csum =0 ; +int flash_command =FLASH_CMD_NONE ; +int err =0 ;
drivers/scsi/aic94xx/aic94xx_init.c line 375
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_init.c +10
-0+ + + cmd_ptr =kmalloc (count*2 ,GFP_KERNEL ); + +if (!cmd_ptr) { + err=FAIL_OUT_MEMORY ; + goto out; + } + +memset (cmd_ptr,0 ,count*2 );
cmd_ptr = kzalloc(count * 2, GFP_KERNEL);
drivers/scsi/aic94xx/aic94xx_init.c
Quoted 9 lines
drivers/scsi/aic94xx/aic94xx_init.c +9
-0+ filename_ptr = cmd_ptr+count; + res =sscanf (buf,"%s %s" , cmd_ptr, filename_ptr); +if (res !=2 ) + { + err =FAIL_PARAMETERS ; + goto out1; + } + +for (i =0 ; flash_command_table[i].code !=FLASH_CMD_NONE ; i++)
{
Review
Quoted 1 line
(quoted diff) +1
-0+ if (!memcmp(flash_command_table[i].command,cmd_ptr,
strlen(cmd_ptr))) {
^Space missing
Quoted 8 lines
drivers/scsi/aic94xx/aic94xx_init.c +8
-0+ flash_command = flash_command_table[i].code; +break ; + } + } +if (flash_command ==FLASH_CMD_NONE ) { + err =FAIL_PARAMETERS ; + goto out1; + }
drivers/scsi/aic94xx/aic94xx_init.c
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_init.c +10
-0+ +if (asd_ha->bios_status ==FLASH_IN_PROGRESS ) { + err =FLASH_IN_PROGRESS ; + goto out1; + } + err =request_firmware (&asd_ha->bios_image, + filename_ptr, + &asd_ha->pcidev->dev); +if (err) { + asd_printk("Failed to load bios image file %s, error
%d\n",
drivers/scsi/aic94xx/aic94xx_init.c
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_init.c +10
-0+ filename_ptr, err); + err =FAIL_OPEN_BIOS_FILE ; + goto out1; + } + + hdr_ptr = (struct bios_file_header *)asd_ha->bios_image->data; + + if ((hdr_ptr->contrl_id.vendor != asd_ha->pcidev->vendor || + hdr_ptr->contrl_id.device != asd_ha->pcidev->device) && + (hdr_ptr->contrl_id.sub_vendor != asd_ha->pcidev->vendor
||
Review
Quoted 1 line
(quoted diff) +1
-0+ hdr_ptr->contrl_id.sub_device !=
asd_ha->pcidev->device)) {
Review
Quoted 2 lines
(quoted diff) +2
-0+ + ASD_DPRINTK("The PCI vendor id or device id does not
match\n");
Review
Quoted 1 line
(quoted diff) +1
-0+ ASD_DPRINTK("vendor=%x dev=%x sub_vendor=%x sub_dev=%x
pci vendor=%x pci
Quoted 1 line
dev=%x \n", +
hdr_ptr->contrl_id.vendor,
^
Superfluous whitespace
Quoted 27 lines
drivers/scsi/aic94xx/aic94xx_init.c +26
-0+ hdr_ptr->contrl_id.device, + hdr_ptr->contrl_id.sub_vendor, + hdr_ptr->contrl_id.sub_device, + asd_ha->pcidev->vendor, + asd_ha->pcidev->device); + err =FAIL_CHECK_PCI_ID ; + goto out2; + } + +if (hdr_ptr->filelen != asd_ha->bios_image->size) { + err =FAIL_FILE_SIZE ; + goto out2; + } + +/* calculate checksum */ +for (i =0 ; i < hdr_ptr->filelen; i++) + csum += asd_ha->bios_image->data[i]; + +if ((csum &0x0000ffff ) != hdr_ptr->checksum) { +ASD_DPRINTK ("BIOS file checksum mismatch\n" ); + err =FAIL_CHECK_SUM ; + goto out2; + } +if (flash_command ==FLASH_CMD_UPDATE ) { + asd_ha->bios_status =FLASH_IN_PROGRESS ; + err =asd_write_flash_seg(asd_ha,&asd_ha->bios_image->data[sizeof(*hdr_ptr)]
Review
Quoted 1 line
(quoted diff) +1
-0+ ,0,hdr_ptr->filelen-sizeof(*hdr_ptr));
^
This comma belongs in the last line.
Review
Quoted 3 lines
(quoted diff) +2
-0+ if (!err) { + err =
asd_verify_flash_seg(asd_ha,&asd_ha->bios_image->data[sizeof(*hdr_ptr)]
Review
Quoted 1 line
(quoted diff) +1
-0+ ,0,hdr_ptr->filelen-sizeof(*hdr_ptr));
^
This one too.
drivers/scsi/aic94xx/aic94xx_init.c line 460
Quoted 13 lines
drivers/scsi/aic94xx/aic94xx_init.c +5
-0+ } + } +else { + asd_ha->bios_status =FLASH_IN_PROGRESS ; + err =asd_verify_flash_seg(asd_ha,&asd_ha->bios_image->data[sizeof(header)]
drivers/scsi/aic94xx/aic94xx_init.c +7
-0+ ,0,hdr_ptr->filelen-sizeof(header)); + } + +out2: +release_firmware (asd_ha->bios_image); +out1: +// free buffer
It's rather obvious what kfree() does, isn't it?
Quoted 3 lines
diff -urN
a/drivers/scsi/aic94xx/aic94xx_sds.cb/drivers/scsi/aic94xx/aic94xx_sds.c---a/drivers/scsi/aic94xx/aic94xx_sds.c2007-10-10 17:13:43.000000000
-0700
Quoted 1 line
+++
b/drivers/scsi/aic94xx/aic94xx_sds.c2007-10-10
17:16:10.000000000
drivers/scsi/aic94xx/aic94xx_sds.c line 33
Quoted 6 lines
-0700 @@ -30,7 +30,7 @@
#include "
aic94xx.h"
#include "aic94xx_reg.h"drivers/scsi/aic94xx/aic94xx_sds.c +1
-1- +#include "aic94xx_sds.h"
I prefer a newline before this comment. YMMV.
Quoted 4 lines
/* ---------- OCM stuff ---------- */
struct
asd_ocm_dir_ent{
drivers/scsi/aic94xx/aic94xx_sds.c line 1092
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +7
-0@@ -1083,3 +1083,443 @@kfree (flash_dir);return err; } +/* +* Function: +* asd_hwi_write_nv_segment() +* +* Description: +* Writes data to an NVRAM segment. +*/
Kernel-doc description?
/**
* asd_hwi_write_nv_segment - Writes data to an NVRAM segment
* @asd_ha: ...
Quoted 15 lines
drivers/scsi/aic94xx/aic94xx_sds.c +15
-0+int +asd_verify_flash_seg (struct asd_ha_struct *asd_ha, +void *src,u32 dest_offset,u32 bytes_to_verify) +{ +u8 *src_buf; +u8 flash_char; +int err; +u32 nv_offset, reg, i; + + + reg = asd_ha->hw_prof.flash.bar; + src_buf =NULL ; + + err =FLASH_OK ; + nv_offset = dest_offset;
drivers/scsi/aic94xx/aic94xx_sds.c line 1117
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ src_buf = (u8 *)src; +for (i =0 ; i < bytes_to_verify; i++) { + + flash_char =asd_read_reg_byte (asd_ha,reg +nv_offset+i); +if (flash_char != src_buf[i]) { + err =FAIL_VERIFY ; +break ; + } + } +return (err);
return err;
Quoted 13 lines
drivers/scsi/aic94xx/aic94xx_sds.c +13
-0+} +/* +* Function: +* asd_hwi_write_nv_segment() +* +* Description: +* Writes data to an NVRAM segment. +*/ +int +asd_write_flash_seg (struct asd_ha_struct *asd_ha, +void *src,u32 dest_offset,u32 bytes_to_write) +{ +u8 *src_buf;
drivers/scsi/aic94xx/aic94xx_sds.c
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+u32 nv_offset, reg, i; +int err; + + + reg = asd_ha->hw_prof.flash.bar; + src_buf =NULL ; + + err =asd_check_flash_type (asd_ha); +if (err) { + ASD_DPRINTK("couldn't find the type of flah(%d)\n",
err);
^^flash, I'd prefer whitespace before the number. In this form someone could
think it's a flash index and not the error code on the first look.
Quoted 4 lines
drivers/scsi/aic94xx/aic94xx_sds.c +4
-0+return err; + } + + nv_offset = dest_offset;
drivers/scsi/aic94xx/aic94xx_sds.c line 1154
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ err =asd_erase_nv_sector (asd_ha, nv_offset,bytes_to_write); +if (err) { +ASD_DPRINTK ("Erase failed at offset:0x%x\n" , + nv_offset); +return err; + } + + err =asd_reset_flash (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err);
^
Whitespace, too.
Quoted 29 lines
drivers/scsi/aic94xx/aic94xx_sds.c +29
-0+return err; + } + + src_buf = (u8 *)src; +for (i =0 ; i < bytes_to_write; i++) { +/* Setup program command sequence */ +switch (asd_ha->hw_prof.flash.method) { +case FLASH_METHOD_A : + { + +asd_write_reg_byte (asd_ha, + (reg +0xAAA ),0xAA ); +asd_write_reg_byte (asd_ha, + (reg +0x555 ),0x55 ); +asd_write_reg_byte (asd_ha, + (reg +0xAAA ),0xA0 ); +asd_write_reg_byte (asd_ha, + (reg + nv_offset + i), + (*(src_buf + i))); +break ; + } +case FLASH_METHOD_B : + { +asd_write_reg_byte (asd_ha, + (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, + (reg +0x2AA ),0x55 ); +asd_write_reg_byte (asd_ha, + (reg +0x555 ),0xA0 );
drivers/scsi/aic94xx/aic94xx_sds.c line 1193
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+asd_write_reg_byte (asd_ha, + (reg + nv_offset + i), + (*(src_buf + i))); +break ; + } +default : +break ; + } +if (asd_chk_write_status (asd_ha, (nv_offset + i), +0 /* WRITE operation */ ) !=0 ) {
Putting the comment on an own line would make it more readable IMHO.
Review line 1194
Quoted 1 line
(quoted diff) +1
-0+ ASD_DPRINTK("aicx: Write failed at
offset:0x%x\n",
drivers/scsi/aic94xx/aic94xx_sds.c line 1207
Quoted 13 lines
drivers/scsi/aic94xx/aic94xx_sds.c +13
-0+ reg + nv_offset + i); +return FAIL_WRITE_FLASH ; + } + } + + err =asd_reset_flash (asd_ha); +if (err) { +ASD_DPRINTK ("couldn't reset flash(%d)\n" , err); +return err; + } +return (0 ); +} +int
Empty line between functions missing. More of this on other places.
Quoted 7 lines
drivers/scsi/aic94xx/aic94xx_sds.c +7
-0+asd_chk_write_status(struct asd_ha_struct *asd_ha, u32 sector_addr, + u8 erase_flag) +{ + u32 reg; +u32 loop_cnt; +u8 nv_data1, nv_data2; +u8 toggle_bit1/*, toggle_bit2*/ ;
drivers/scsi/aic94xx/aic94xx_sds.c line 1224
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ +/* +* Read from DQ2 requires sector address +* while it's dont care for DQ6 +*/ +/* read_addr = asd->hw_prof.nv_flash_bar + sector_addr;*/ + reg = asd_ha->hw_prof.flash.bar; + loop_cnt =50000 ; + +while (loop_cnt) {
for-loop?
drivers/scsi/aic94xx/aic94xx_sds.c
Quoted 5 lines
drivers/scsi/aic94xx/aic94xx_sds.c +5
-0+ nv_data1 =asd_read_reg_byte (asd_ha, reg); + nv_data2 =asd_read_reg_byte (asd_ha, reg); + + toggle_bit1 = ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ6) + ^ (nv_data2 &
FLASH_STATUS_BIT_MASK_DQ6));
Review line 1231
Quoted 2 lines
(quoted diff) +2
-0+ /* toggle_bit2 = ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ2) + ^ (nv_data2 &
FLASH_STATUS_BIT_MASK_DQ2));*/
drivers/scsi/aic94xx/aic94xx_sds.c line 1234
Quoted 3 lines
drivers/scsi/aic94xx/aic94xx_sds.c +3
-0+ +if (toggle_bit1 ==0 ) { +return (0 );
return 0;
drivers/scsi/aic94xx/aic94xx_sds.c
Quoted 9 lines
drivers/scsi/aic94xx/aic94xx_sds.c +9
-0+ }else { +if (nv_data2 &FLASH_STATUS_BIT_MASK_DQ5 ) { + nv_data1 =asd_read_reg_byte (asd_ha, + reg); + nv_data2 =asd_read_reg_byte (asd_ha, + reg); + toggle_bit1 = + ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ6) + ^ (nv_data2 &
FLASH_STATUS_BIT_MASK_DQ6));
drivers/scsi/aic94xx/aic94xx_sds.c
Quoted 3 lines
drivers/scsi/aic94xx/aic94xx_sds.c +3
-0+/* +toggle_bit2 = +((nv_data1 &
FLASH_STATUS_BIT_MASK_DQ2)
Review line 1247
Quoted 1 line
(quoted diff) +1
-0+ ^ (nv_data2 &
FLASH_STATUS_BIT_MASK_DQ2));
Quoted 4 lines
drivers/scsi/aic94xx/aic94xx_sds.c +4
-0+*/ +if (toggle_bit1 ==0 ) { +return 0 ; + }
drivers/scsi/aic94xx/aic94xx_sds.c
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ } + } + loop_cnt--; + +/* +* ERASE is a sector-by-sector operation and requires +* more time to finish while WRITE is byte-byte-byte +* operation and takes lesser time to finish. +* +* For some strange reason a reduced ERASE delay gives
different
Review line 1262
Quoted 1 line
(quoted diff) +1
-0+ * behaviour across different spirit boards. Hence we
set
drivers/scsi/aic94xx/aic94xx_sds.c line 1272
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+* a optimum balance of 50mus for ERASE which works well +* across all boards. +*/ +if (erase_flag) { +udelay (FLASH_STATUS_ERASE_DELAY_COUNT ); + }else { +udelay (FLASH_STATUS_WRITE_DELAY_COUNT ); + } + } +return (-1 );
return -1;
drivers/scsi/aic94xx/aic94xx_sds.c line 1280
Quoted 8 lines
drivers/scsi/aic94xx/aic94xx_sds.c +8
-0+} +/* +* Function: +* asd_hwi_erase_nv_sector() +* +* Description: +* Erase the requested NVRAM sector. +*/
Kerneldoc again?
Review line 1282
Quoted 2 lines
(quoted diff) +2
-0+int +asd_erase_nv_sector(struct asd_ha_struct *asd_ha, u32 flash_addr,u32
size)
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+{ +u32 reg; +u32 sector_addr; + reg = asd_ha->hw_prof.flash.bar; +/* sector staring address */ + sector_addr = flash_addr &FLASH_SECTOR_SIZE_MASK ; +/* +* Erasing an NVRAM sector needs to be done in six consecutive +* write cyles. +*/
drivers/scsi/aic94xx/aic94xx_sds.c
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+while (sector_addr < flash_addr+size) { +switch (asd_ha->hw_prof.flash.method) { + +case FLASH_METHOD_A : +asd_write_reg_byte (asd_ha, (reg +0xAAA ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x55 ); +asd_write_reg_byte (asd_ha, (reg +0xAAA ),0x80 ); +asd_write_reg_byte (asd_ha, (reg +0xAAA ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x55 ); + asd_write_reg_byte(asd_ha, (reg + sector_addr),
0x30);
drivers/scsi/aic94xx/aic94xx_sds.c
Quoted 9 lines
drivers/scsi/aic94xx/aic94xx_sds.c +9
-0+break ; + +case FLASH_METHOD_B : +asd_write_reg_byte (asd_ha, (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x2AA ),0x55 ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0x80 ); +asd_write_reg_byte (asd_ha, (reg +0x555 ),0xAA ); +asd_write_reg_byte (asd_ha, (reg +0x2AA ),0x55 ); + asd_write_reg_byte(asd_ha, (reg + sector_addr),
0x30);
Quoted 5 lines
drivers/scsi/aic94xx/aic94xx_sds.c +5
-0+break ; + +default : +break ; + }
drivers/scsi/aic94xx/aic94xx_sds.c line 1326
Quoted 10 lines
drivers/scsi/aic94xx/aic94xx_sds.c +10
-0+ +if (asd_chk_write_status (asd_ha, sector_addr, +1 /* ERASE operation */ ) !=0 ) { +return FAIL_ERASE_FLASH ; + } + + sector_addr +=FLASH_SECTOR_SIZE ; + } + +return (0 );
return 0;
Greetings,
Eike