当前位置:Linux教程 - Linux - 硬盘容量的修改要

硬盘容量的修改要



         以下是SEAGATE的一段升级程序(局部),现在应该还可以使用。从这段程序里s.scsi_command[0]= 0x3B……0x05……0x07可以看到,升级的过程实际是一个传送过程,先把代码送到BUFFER里执行,后面的指令就是状态监视。

    对硬盘来说是需要专门的方式进行传送升级代码的,不然,你的代码会被硬盘当成DATA写到了盘片上。

    编译环境是使用IP *Works! C++Linux Edition

    声明:当年很多和SEAGATE硬盘相关的软件大都使用或借鉴这段程序,所以运行的流程在一定程度上和其他的软件有相似的地方,甚至窗口位置都一样。升级FIRMWARE的过程特别简单.
    该程序具有版权,请大家不要原封不动的抄,理解了后可以变换变换,除非得到授权才能照抄发布自己的东西。

    代码:
    void download_firmware()
    {
    SCSI *dl;
    int w, key, fh, choice, org_asa, new_asa, n= 0, off= 0;
    unsigned bufsize= 8*1024, rv;
    char *filename, *p;
    long l, j, i, jj, offset;

    if (!is_seagate_disk(inq))
    message("WARNING !rn"
    "rn"
    "Download firmware is only tested with Seagate disk drives.");

    filename= calloc(1, 128);
    if (!filename)
    {
    printf("Error allocating %u bytes of memoryn", 128);
    exit(0);
    }

    strcpy(filename, config->download_file);
    key= edit_string_window(filename, 70, "Enter firmware file to download");
    if (key== KEY_ENTER)
    {
    fh= open(filename, O_RDONLY|O_BINARY);
    if (fh!= -1)
    {
    w= window_create(-1, 9, 60, 18, BLUEs.host_adapter= inq->s.host_adapter;
    dl->s.target_id= inq->s.target_id;
    dl->s.lun= inq->s.lun;

    dl->s.scsi_command[0]= 0x3B;
    if (off== 0)
    {
    p= farmalloc(l);
    if (p== NULL)
    {
    message("Error allocating %lu bytes", l);
    einde(-1);
    }

    dl->s.scsi_command[1]= 0x05;
    dl->s.data_buffer= p;
    dl->s.data_buffer_length= l;
    }
    else
    dl->s.scsi_command[1]= 0x07;

    *(unsigned long *)&dl->s.scsi_command[5]=
    swaplong(dl->s.data_buffer_length);

    if (off== 1)
    {
    offset= 0;
    j= l / bufsize;
    jj= l % bufsize;
    gotoxy(1,3);
    cprintf("%lu blocks of %uK and %lu bytesrn",
    j, (bufsize >> 10), jj);
    cprintf("Block:");
    for (i= 0; i s.data_buffer, bufsize, &rv);
    *(unsigned long *)&dl->s.scsi_command[2]=
    swaplong(offset);
    if (rv== bufsize)
    scsi_execute(dl, 1);
    else
    {
    message("Error while reading firmware file");
    einde(-1);
    }

    gotoxy(8,4);
    cprintf("%lu", i);
    offset+= rv;
    }

    if (jj)
    {
    gotoxy(20,3);
    _dos_read(fh, dl->s.data_buffer, jj, &rv);
    *(unsigned long *)&dl->s.scsi_command[2]=
    swaplong(offset);
    *(unsigned long *)&dl->s.scsi_command[5]=
    swaplong(rv);
    if (rv== jj)
    scsi_execute_bg(dl);
    else
    {
    message("Error while reading firmware file");
    einde(-1);
    }

    gotoxy(26,4);
    cprintf("%u", i);
    offset+= rv;
    }
    }
    else
    {
    cprintf("Reading file %s, %lu KB", filename, l >> 10);
    rv= file_read_into_memory(fh, p, l);
    if (rv)
    {
    message("Error while reading firmware file");
    einde(-1);
    }
    scsi_execute_bg(dl);
    }

    gotoxy(1,4);
    clreol();
    cprintf("Download status :");

    n= 0;
    while(dl->s.status== 0)
    {
    gotoxy(18,4);
    putch(wiekje[n++]);
    if (!wiekje[n]) n= 0;
    gotoxy(19,4);
    cprintf("%-10.10s", aspi_status_name(dl->s.status));
    delay(250);
    }

    gotoxy(18,4);
    putch(' ');
    gotoxy(19,4);
    cprintf("%-10.10s", aspi_status_name(dl->s.status));

    if (dl->s.status!= 1)
    {
    gotoxy(1,5);
    print_sense_info_short(dl);
    }
    else
    {
    gotoxy(1,6);
    cprintf("Waiting for unit");
    wait_unit_ready(inq);

    new_asa= seagate_asa_level(inq);
    gotoxy(1,6);
    clreol();
    cprintf("New ASA level is ASA%u", new_asa);

    if (org_asa!= new_asa)
    {
    message("You upgraded your drive to a newrn"
    "ASA level, drive needs low level format !rn"
    /*大家注意这点,升级是有风险的,这个信息只是其中一个很小的风险,由于ASA级别的改变,需要你低级格式化硬盘,哈哈数据没啦!
    SEAGATE厂的ASA为2。其他计算机大厂的ASA有的为0有的为1……,自己找些资料参考吧。
    */
    "rn"
    "%s", fortune(fun_message));
    }
    }

    if (off== 0)
    {
    dl->s.data_buffer= NULL;
    dl->s.data_buffer_length= 0;
    farfree(p);
    }
    scsi_destroy(dl);

    pause();
    }
    }

    close(fh);
    window_destroy(w);
    strcpy(config->download_file, filename);
    cfg_save();
    }
    else
    message("Error opening file %snr->%s", filename, sys_errlist[errno]);
    }


    free(filename);
    SEAGATE ST336607的部分模式页在这里,自己修改响应的值再写回去就可以了。
    04 3c d9 40 00 00 02 00
    01 0a c8 0b ff 00 00 00 05 00 27 10
    02 0e 00 00 00 0a 00 00 00 00 00 00 10 00 00 00
    03 16 11 aa 00 00 00 08 00 00 02 d0 02 00 00 01 00 66 00 66 40 00 00 00
    04 16 00 c2 bf 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 31 00 00
    07 0a 08 0b ff 00 00 00 00 00 27 10
    08 12 10 00 ff ff 00 00 ff ff ff ff 00 10 00 00 00 00 00 00
    0a 0a 00 00 00 00 00 00 00 00 03 00
    19 06 01 00 ff ff 00 00
    1a 0a 00 03 00 00 00 01 00 00 00 04
    1c 0a 88 04 00 00 8c a0 00 00 00 00
    下面给你一段参考汇编程序,希自己的硬盘改成自己的名字望对你有用。

    代码:

    .MODEL large, C
    .DATA

    .CODE

    extrn AspiEntryPoint:dword
    public SRBexec

    SRBexec PROC C, segm:WORD, ofs:WORD

    mov ax, segm
    push ax
    mov ax, ofs
    push ax
    call DWORD PTR [AspiEntryPoint]
    add sp, 4
    ret
    SRBexec ENDP

    public swaplong

    swaplong PROC C, long1,long2:WORD

    mov ax, long2
    xchg al, ah
    mov dx, long1
    xchg dl, dh

    ret
    swaplong ENDP

    public swapint

    swapint PROC C, int1:WORD

    mov ax, int1
    xchg al, ah

    ret
    swapint ENDP

    end


    有个文件名叫sgdskfl.c,是INTEL的工程师Andy cress写的,算法上和SEAGATE的大致相同,另外还包括很多其他可移动SCSI设备和流SCSI设备的方案。

    Andy Cress的编程风格很好,具有很多注释,大家应该很容易看懂。不过由于页面显示程序的缘故,所有程序代码左边的空格均无效了,因此全靠左显示,给大家浏览带来了不便。如果希望浏览更好看的代码,请访问[STOL]存储社区

    代码:

    /*--------------------------------------------------------------------------
    Filename : sgdskfl.c
    Abstract : SCSI Generic Disk Firmware Load tool
    Operation System: Linux 2.2 or greater
    Copyright ? Intel Corporation 2001
    Author: Andy Cress
    ----------- Change History -----------------------------------------------
    05/01/01 v0.70 ARCress created
    07/17/01 v0.91 ARCress added code to download servo also
    added write_buffers code to do multi-part dl.
    08/08/01 v0.92 ARCress fixed write_buffers logic for IBM disks.
    09/05/01 v0.93 ARCress message cleanup
    09/28/01 v0.94 ARCress turn off sg_debug in afterdl
    10/15/01 v0.95 ARCress fixed IBM chunk size
    10/30/01 v1.0 ARCress cleanup includes & indent -kr
    11/09/01 v1.0 ARCress enlarged devstat2 from 80 to 120 for overrun
    11/14/01 v1.0 ARCress added default directory for image files.
    04/11/02 v1.1 ARCress path changes for log & image files,
    set do_numeric=1 default
    05/08/02 v1.3 ARCress tune sg_debug level down to 5 by default
    08/15/02 v1.4 ARCress moved common subroutines to sgcommon
    added more usage messages
    09/03/02 v1.5 ARCress streamline display for errors in get_scsi_info
    01/08/03 v1.6 ARCress include Quantum in getimage:fscanmodel.
    ----------- Des cription --------------------------------------------------
    sgdskfl
    Sequence of events for this utility:
    * List each device on the system with firmware versions.
    * User selects a device for firmware load (automatic if using -m)
    * Read the firmware image file for the selected disk and verify that it is
    valid.
    * Verify that the disk is present and ready
    * Close all open files, flush the adapter, sync any data to the SCSI disks.
    * Write the firmware image to the disk using a 'write buffer' SCSI command
    with large reserved buffer or scatter/gather.
    * Wait 5 (or specified number) seconds
    * Verify that the disk comes ready again using SCSI test_unit_ready commands,
    and start_unit or scsi_reset to recover if not.
    * If the '-m' option was used, repeat writing the firmware for each disk of
    this model.
    sgdskfl [-e -m diskmodel -f imagefile -t secdelay -x]
    Options:
    -e Do not write to any files. Usually a log file (sgdskfl.log) is created
    and written to, up until the firmware download begins on root.
    -m Automatically download all drives that match this model string.
    Note that this option will initiate a reboot after it is done,
    unless option u is also specified.
    -f Specify this filename for the firmware image. Normally, this option is
    not used and the filename is formed using the first 8 characters of the
    model, with the ".lod" extension. For example: "st39140w.lod".
    Note that this utility uses the raw firmware image without any added
    headers.
    -t Specifies the number of seconds to delay after the firmware is written
    and the program attempts to test if the unit is ready again.
    Default is 10 seconds.
    -r Recover a non-ready drive by updating its firmware.
    Don't test if the drive is ready or not.
    -x Outputs extra debug messages
    -d Specify a unix device name
    ----------------------------------------------------------------------------*/
    /*-------------------------------------------------------------------------
    Copyright ? 2002, Intel Corporation
    All rights reserved.
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
    a.. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
    b.. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.
    c.. Neither the name of Intel Corporation nor the names of its contributors
    may be used to endorse or promote products derived from this software
    without specific prior written permission.
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    -------------------------------------------------------------------------*/
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include "sgsub.h"
    #include "sgcommon.h"

    /* External Functions prototypes */
    extern void setbuf(FILE * stream, char *buf);
    extern int errno;
    extern char fdebugsub; /* used in sgsub.c */
    extern FILE *dbgout; /* used in sgsub.c */

    #define EBUFF_LEN 80
    #define MAX_ERRORS 4

    /* Global data definitions */
    char progver[] = "1.6"; /* program version */
    char *progname = "sgdskfl"; /* program name */
    char logfile[] = "/var/log/sgdskfl.log"; /* log filename */
    char fwsufx[] = ".lod"; /* suffix for firmware image filenames */
    char model[20] = ""; /* default model string */
    char fsetfile = 0;
    char fwfile[20] = "default"; /* default firmware filename (8.lod) */
    char defdir[30] = "/usr/share/scsirastools/"; /*default directory for fw files*/
    char devname[80] = "/dev/sda"; /* UNIX device name (w path) */
    char svfile[20] = "default"; /* default servo filename (8.tms) */
    int sdelay = 10; /* num sec to delay before TUR */
    FILE *fdlog = NULL; /* log file des criptor */
    FILE *fdmsg; /* file des criptor for messages */
    char fautomodel = 0; /* =1 to automatically do all of a model */
    char filesok = 1; /* =1 if ok to write to files */
    char fdebug = 0; /* =1 for debug messages */
    char fdoreset = 0; /* =1 if need to do reset for this drive */
    char flogopen = 0; /* =1 if log file is open */
    char fnotur = 0; /* =1 to not try TUR */
    char fdevname = 0; /* =1 if device name specified */
    int do_numeric = 1; /* NUMERIC_SCAN_DEF; */
    uchar sense_buffer[80]; /* buffer for sense data */
    char output[132]; /* message output buffer */
    char output2[80]; /* extra message output buffer */
    uchar devstat[80]; /* used for inquiry & device status */
    uchar devstat2[120]; /* used for Seagate inquiry2 & Mylex stat */
    uchar disk_buffer[0x200]; /* 512 bytes, used for misc scsi data */
    uchar *image_buffer; /* malloc'd firmware image buffer */
    uchar *servo_buffer; /* malloc'd servo buffer */
    int idev = 0;
    int ndev = 0;
    DEVLIST_TYPE devlist[32];
    char *devtype_array[11] = {
    "Disk ",
    "Tape ",
    "Printer",
    "Procesr",
    "WORM ",
    "CD-ROM ",
    "Scanner",
    "Optical",
    "Med Chg",
    "Comm ",
    "Unknown"
    };

    /* Local subroutines */
    int writeimage(int idx, uchar * imgbuf, ulong len, char fservo);
    ulong getimage(int idx, uchar ** pbuf, char fservo);
    int beforedl(int idx, int *pnumrdy);
    int afterdl(void);

    int main(int argc, char **argv)
    {
    int i, c, idx;
    char response = 0;
    ulong size; /* size of fw */
    ulong size_sv; /* size of servo */
    int runl;
    short sts, rc;
    ulong ltime1;
    char fname[64];
    char ebuff[EBUFF_LEN];
    int sg_fd;
    int flags;
    int res, k;
    int eacces_err = 0;
    int num_errors = 0;
    DEVFS_LIST devfs_components = {0,0,0,0,0};

    // progname = argv[0];
    fdmsg = stdout; /* set default fdmsg */
    while ((c = getopt(argc, argv, "enxrf:m:t:d:?")) != EOF)
    switch ? {
    case 'e':
    filesok = 0;
    break;
    case 'x':
    fdebug = 1;
    break;
    case 'r':
    fnotur = 1;
    break;
    case 'n':
    do_numeric = 0;
    break;
    case 'f':
    strcpy(fwfile, optarg);
    fsetfile = 1;
    break;
    case 'm':
    fautomodel = 1; /* automatically do all of this model */
    strcpy(model, optarg);
    break;
    case 't':
    sdelay = atoi(optarg); /* time to delay */
    break;
    case 'd':
    strcpy(devname, optarg); /* specify a unix device name */
    fdevname = 1;
    break;
    case '?':
    default:
    printf("Usage: %s [-m diskmodel -f imagefile -t secdelay -enrx]n",
    progname);
    printf(" -m Automatically download all drives that match this model stringn");
    printf(" -f Specify filename for firmware image instead of defaultn");
    printf(" -t Time in seconds to delay after the firmware is written, default 10n");
    printf(" -n Turn off Numeric, use alpha device names insteadn");
    printf(" -e Do not write to any files, so don't use the log filen");
    printf(" -r Recover a non-ready drive by updating its firmwaren");
    printf(" -x Outputs extra debug messagesn");
    exit(1);
    }
    /* only run this as superuser */
    i = geteuid();
    if (i > 1) {
    printf("Not superuser (%d)n", i);
    exit(1);
    }
    /* check for run-level 1 */
    {
    runl = 1;
    /* how to check this? */
    if (fdebug) {
    /*DEBUG*/ printf("sdelay = %d secn", sdelay);
    printf("run-level = %dn", runl);
    }
    }
    if (runl != 1) { /* show warning if not run level 1 */
    printf
    ("Warning: Make sure disks are inactive during firmware downloadn");
    // dont exit, just give a warning.
    }
    /* open log file */
    if (filesok)
    fdlog = fopen(logfile, "a+");
    if (fdlog == NULL) {
    flogopen = 0;
    filesok = 0;
    fdlog = stderr;
    } else { /* logfile open successful */
    flogopen = 1;
    time((time_t *) & ltime1);
    fprintf(fdlog, "n--- %s v%s log started at %s", progname, progver,
    ctime((long *) fprintf(fdlog, "model: %sn", model);
    fprintf(fdlog, "fw file: %sn", fwfile);
    }
    fdebugsub = fdebug;
    dbgout = fdlog;
    /* loop to display disk choices and do downloads */
    while (1) {
    /* display header */
    printf("n");
    printf(" %s utility v%s for SCSI disksn",
    progname, progver);
    printf
    (" ******************************************n");
    if (flogopen)
    printf("Log file %s is open, debug=%dn", logfile, fdebug);
    printf
    ("nNum Name [bus:ch:id:lun] Type Vendor Device_Model FW__ Serial#_ Servo___n");
    /* get SCSI Device Info */
    idev = 0;
    flags = O_RDWR; /* could use OPEN_FLAG if read-only. */
    num_errors = 0;
    for (k = 0; (k 0) {
    res = close(sg_fd);
    if (res vendorid,
    "SEAGATE", 7) != 0)
    fservo = 3; /* Seagate tapes use split buffer method 3 */
    /* Tecmar, Travan, Wangtek, WangDAT tapes use method 2 */
    else
    fservo = 2; /* use split buffer method 2 */
    }
    else
    if (
    (strncmp
    ((char *) scsi_inq->vendorid, "IBM",
    3) == 0)
    &&
    (strncmp
    ((char *) scsi_inq->productid, "ST",
    2) != 0))
    /* for all IBM disks, except Seagate OEM */
    fservo = 4; /* IBM disks use split buffer method X */
    else
    fservo = 0; /* normal, all one buffer */
    if (size > 0) { /* flash firmware */
    rc =
    writeimage(i, image_buffer, size,
    fservo);
    free(image_buffer); /*allocated in getimage() */
    if (fdebug && rc != 0) {
    showit((char *) disk_buffer); /*writes saved messages */
    quit(rc);
    }
    }
    if (size_sv > 0) { /* flash servo */
    rc =
    writeimage(i, servo_buffer, size_sv,
    1);
    free(servo_buffer); /*allocated in getimage() */
    }
    }
    if (!fautomodel)
    i = ndev; /* only do one if interactive */
    } /*endfor each disk */
    rc = afterdl();
    } /*endif image ok */
    } /*end else index ok */
    } /*end else do download */
    else { /* response not d or q */
    printf("Invalid input [%c], enter 'd' or 'q'.n", response);
    }
    if (fautomodel) { /* then done */
    if (0) { /* if root is down and likely to hang otherwise, */
    printf("Rebooting ...n");
    sleep(3);
    // /* do reboot without shutdown */
    } else
    quit(0); /* normal exit, successful */
    } else { /* interactive, go to menu again */
    do_pause();
    }
    } /*end while(1) */
    } /*end main() */

    ulong getimage(int idx, uchar ** pbuf, char fservo)
    {
    ulong filsz;
    FILE *fdimg;
    struct stat statbuf;
    struct SCSI_INQUIRY *scsi_inq;
    char modelx[20];
    char *filenm;
    char fullfilenm[80];
    char *buf;
    int i, rc;
    *pbuf = NULL;
    scsi_inq = (struct SCSI_INQUIRY *) devlist[idx].inq;
    if (fautomodel)
    strncpy(modelx, model, strlen(model));
    else
    strncpy(modelx, (char *) scsi_inq->productid, 16);
    for (i = 0; i vendorid);
    showit(output);
    }
    if (!fsetfile) { /* build the default filename */
    for (i = 0; i vendorid, "SEAGATE", 7) == 0) {
    if (modelx[7] == 'W')
    modelx[7] = 'N'; /*always match with narrow */
    modelx[8] = 0; /* truncate to 8 chars for search */
    fscanmodel = 1;
    } else if (strncmp((char *) scsi_inq->vendorid, "IBM", 3) == 0)
    fscanmodel = 1;
    else if (strncmp((char *) scsi_inq->vendorid, "MAXTOR", 6) == 0)
    fscanmodel = 1;
    else if (strncmp((char *) scsi_inq->vendorid, "QUANTUM", 7) == 0)
    fscanmodel = 1;
    /* HITACHI and FUJITSU only have partial model strings to match */
    if (fscanmodel) { /* scan image buffer for model(productid) */
    /* A variable offset in the file has a list of the target models. */
    rc = findmatch(buf, filsz, modelx, strlen(modelx), 1); /*also ignore case */
    if (rc == -1) {
    sprintf(output, "Image does not match model %sn", modelx);
    showit(output);
    fclose(fdimg);
    free(buf);
    return (0); /* size = 0 */
    }
    if (fdebug) {
    sprintf(output, "Image file matches model %sn", modelx);
    showit(output);
    }
    } /*endif scanmodel */
    }
    /*endif not servo */
    *pbuf = buf;
    fclose(fdimg);
    return (filsz);
    } /*end getimage() */

    int write_buffers(int sgfd, uchar * buf, ulong len, uchar fservo)
    {
    int sts;
    ulong j, sz_left;
    ulong max_chunk;
    uchar save_mode;
    uchar bufid;
    uchar ebuf[20];
    if (fservo >= 2) {
    if (fservo == 3) { /* Seagate tapes */
    max_chunk = 0x4000;
    save_mode = 0x07;
    } else if (fservo == 2) { /* other tapes */
    max_chunk = 0x8000;
    save_mode = 0x05;
    } else // if (fservo == 4) { /* IBM disks */
    {
    max_chunk = 0x8000; /* get this from mode page C7, bytes 16-18 */
    save_mode = 0x05;
    if (fdebug)
    fprintf(fdlog, "IBM split buffer mode, chunk size = %ldn",
    max_chunk);
    j = 0;
    sz_left = len;
    bufid = 0;
    while (sz_left > max_chunk) {
    /* Note that it uses mode 05 for every chunk, not just last one */
    sts =
    write_buffer(sgfd, &buf[j], max_chunk, save_mode,
    bufid);
    if (sts != 0) {
    unsigned int k, a, q;
    int rc;
    rc = get_sense(sts, ebuf);
    k = ebuf[2] & 0x0f; /*Sense Key */
    a = ebuf[12];
    /*ASC*/ q = ebuf[13];
    /*ASCQ*/
    sprintf(output, "wb sense error: %x/%x/%xn", k, a,
    q);
    showit(output);
    if (k == 03 && a == 0x30)
    printf("Overlay upload errorn");
    else if ((k == 2 || k == 3 || k == 4) &&
    (a == 0x40 && q max_chunk) {
    sts = write_buffer(sgfd, &buf[j], max_chunk, 0x04, bufid);
    if (sts != 0)
    return (sts);
    sz_left -= max_chunk;
    j += max_chunk;
    }
    sts = write_buffer(sgfd, &buf[j], sz_left, save_mode, bufid);
    }
    /*endif split buffer scheme */
    else { /* fservo == 0, or fservo == 1 */
    /* Send it all as one big buffer */
    sts = write_buffer(sgfd, buf, len, 0x05, 0L);
    }
    return (sts);
    } /* end write_buffers() */


    int writeimage(int idx, uchar * imgbuf, ulong len, char fservo)
    {
    int sts;
    int devfd;
    int isave;
    ulong ltime, ltime1, ltime2;
    ulong ltime3;
    int i, rc, rcdl;
    int k, a, q;
    char *tag;
    uchar ch, dv;
    isave = idx;
    rcdl = 0;
    /* Download firmware to this disk */
    {
    rcdl = 0;
    fdoreset = 0;
    if (!fautomodel)
    idx = isave; /* only do selected disk */
    devfd = devlist[idx].sgfd;
    ch = devlist[idx].chn;
    dv = devlist[idx].tgt;
    if (devlist[idx].fdoit == 1) {
    if (fautomodel) {
    /* Sometimes next device may have a unit attention/reset check
    * condition pending, so clear that first before the write_buffer.
    */
    sts = test_unit_ready(devfd, 0);
    if (fdebug)
    fprintf(fdlog, "Extra test_unit_ready sts = %xn",
    sts);
    }
    time((time_t *) & ltime1); // get the start time
    /* start the firmware download */
    if (fservo == 1)
    tag = "Servo";
    else
    tag = "Firmware";
    sprintf(output, "Downloading %s image to disk %d %s",
    tag, idx, ctime((long *) // ctime outputs a 'n' at end
    showit(output);
    sts = write_buffers(devfd, imgbuf, len, fservo);
    if (sts) {
    rcdl = sts;
    sprintf(output, "[%d] Error %d in writing buffern", idx,
    sts);
    showit(output); // fdlog closed
    if (fdebug || !fautomodel) {
    return (rcdl); // (only if debug on)
    }
    }
    if (fautomodel && rcdl != 0) {
    /* Save error for logging later */
    sprintf(output, "[%d] %s download error, status = 0x%xn",
    idx, tag, rcdl);
    strcat((char *) disk_buffer, output);
    /* Try to restart the drive, even if the download failed. */
    return (rcdl); /*skip to next one if error */
    }
    // Test if Unit is Ready again
    sprintf(output, "Waiting for disk to come ready again ");
    showit(output);
    sleep(sdelay); /* wait for the drive to reset and come ready */
    for (i = 0; i productid, 8);
    model[8] = 0; /*stringify */
    }
    for (idx = 0; idx productid, 8) == 0) { /* do only ones of the same disk product id */
    sts = test_unit_ready(sgfd, 0);
    if (sts == SCHECK_CND) { /* not ready initially, try to make it ready */
    i = get_sense(sts, sense_buffer);
    k = sense_buffer[2] & 0x0f; /*Sense Key */
    a = sense_buffer[12];
    /*ASC*/ q = sense_buffer[13];
    /*ASCQ*/ if (k == 2 && a == 4 && q == 2) {
    /* 02-04-02 means it needs a start command, so issue it. */
    sts = start_unit(sgfd);
    if (fdebug) {
    /*DEBUG*/ printf("nStart Unit: sts=%d, ", sts);
    if (sts == SCHECK_CND) {
    rc = get_sense(sts, sense_buffer);
    printf("sense data: %x %x %xn",
    sense_buffer[2] & 0x0f,
    sense_buffer[12], sense_buffer[13]);
    }
    }
    } /*endif 02-04-02 */
    sts = test_unit_ready(sgfd, 1); /* try again */
    }
    if (sts) {
    sprintf(output, "[%d] Error %d from Test Unit Readyn",
    idx, sts);
    showit(output);
    devlist[idx].fdoit = 0;
    if (fnotur) {
    devlist[idx].fdoit = 1;
    nrdy++;
    }
    } else {
    devlist[idx].fdoit = 1;
    sprintf(output, "Device [%d] is ready for downloadn",
    idx);
    showit(output);
    nrdy++; /* number ready to download */
    }
    } else
    devlist[idx].fdoit = 0; /* not same product id */
    if (!fautomodel)
    idx = ndev; /* end loop */
    } /* end for devlist TUR loop */
    *pnumrdy = nrdy; /* set return value */
    if (nrdy == 0) {
    sprintf(output, "There are no ready devices for model %s.n",
    model);
    showit(output);
    return (sts);
    } else {
    if (nrdy > 1)
    pl = "s";
    else
    pl = "";
    sprintf(output, "Starting download process for %d disk%s.n", nrdy,
    pl);
    showit(output);
    }
    closelog(); /* sets flogopen to false */
    filesok = 0; /* allows files to be opened again */
    fflush(fdmsg); /* flush stdout/stderr for messages */
    setbuf(fdmsg, NULL); /* set for unbuffered writes */
    sync();
    sync(); /* write all UNIX buffers to disk */
    sleep(2);
    /* can't have any more disk IOs from here on */
    if (0) { /* fumntroot) *//* unmount root by default, skip it if user says not to. */
    fprintf(fdmsg, "Unmounting root ...");
    // rc = uadmin(4, 128, 0); /* unmount root fs */
    if (rc == 0)
    fprintf(fdmsg, "donen");
    else
    fprintf(fdmsg, "rc = %dn", rc);
    // frootdown = 1;
    }
    /* Take all drives offline first if specified. */
    disk_buffer[0] = 0; /* used for messages later */
    return (rcdl);
    } /*end beforedl() */


    int afterdl(void)
    {
    int i, sts;
    sts = 0;
    /* Bring all drives online again if raid */
    /* done, all drives should be ready now */
    filesok = 1; /* allows files to be opened again */
    showit((char *) disk_buffer); /* writes saved messages */
    for (i = 0; i 0) {
    sts = set_sg_debug(devlist[I.sgfd, 0);
    if (sts && fdebug)
    fprintf(fdlog, "[%d] cant clear debug flag, sts=%d errno=%dn",
    i, sts, errno);
    close(devlist[I.sgfd); /*opened in beforedl() */
    devlist[I.sgfd = 0;
    }
    }
    return (sts);
    } /*end afterdl() */

    /* end sgdskfl.c */


    在调用的时候,使用21号中断得到入口另外说明一点,GLIST是可以读取(0X37)清除(格式化)的,但是清楚以后故障还会存在。

    再放一段程序便于你们理解。

    代码:

    int glist(SCSI *sp)
    {
    SCSI *s;
    int al= 8, retval= -1, rv, format;
    char format_mask[]= { 0x00, 0x04, 0x05, 0 };
    int format_size[]= { 4,8,8,0 };

    s= scsi_init(al);
    idcpy(s, sp);

    s->s.scsi_command[0]= 0x37;
    s->s.scsi_command[2]= 0x08;
    *(unsigned int *) &s->s.scsi_command[7]= swapint(al);

    for (rv= 0, format= 0; format s.scsi_command[2]&= 0xf8;
    s->s.scsi_command[2]|= format_mask[format];
    rv= scsi_execute(s, 0);
    }
    format--;

    if (rv== 1)
    {
    retval= swapint(*(unsigned int *)&s->s.data_buffer[2])
    format_size[format];
    }

    scsi_destroy(s);
    return(retval);
    }


    还有南桥芯片中都会有一个256字节的CMOS&nbspRAM芯片,它就是用来存储BIOS的设置信息。你可以去看看VIA的VT82C586B、VT82C686A、VT82C686B和最新的几款南桥以及Intel的82371AB(用于440系列家族)、82801AA、82801BA等ICH(用于8xx系列家族)的技术说明文档

    编辑:QuanNing
    发布人:root 来自: