Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/scsicam.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * scsicam.c - SCSI CAM support functions, use for HDIO_GETGEO, etc.
        !             3:  *
        !             4:  * Copyright 1993, 1994 Drew Eckhardt
        !             5:  *      Visionary Computing 
        !             6:  *      (Unix and Linux consulting and custom programming)
        !             7:  *      [email protected]
        !             8:  *     +1 (303) 786-7975
        !             9:  *
        !            10:  * For more information, please consult the SCSI-CAM draft.
        !            11:  */
        !            12: 
        !            13: /*
        !            14:  * Don't import our own symbols, as this would severely mess up our
        !            15:  * symbol tables.
        !            16:  */
        !            17: #define _SCSI_SYMS_VER_
        !            18: #define __NO_VERSION__
        !            19: #include <linux/module.h>
        !            20: 
        !            21: #include <linux/fs.h>
        !            22: #include <linux/genhd.h>
        !            23: #include <linux/kernel.h>
        !            24: #include <linux/blk.h>
        !            25: #include "scsi.h"
        !            26: #include "hosts.h"
        !            27: #include "sd.h"
        !            28: 
        !            29: static int partsize(struct buffer_head *bh, unsigned long capacity,
        !            30:     unsigned int  *cyls, unsigned int *hds, unsigned int *secs);
        !            31: static int setsize(unsigned long capacity,unsigned int *cyls,unsigned int *hds,
        !            32:     unsigned int *secs);
        !            33: 
        !            34: /*
        !            35:  * Function : int scsicam_bios_param (Disk *disk, int dev, int *ip)
        !            36:  *
        !            37:  * Purpose : to determine the BIOS mapping used for a drive in a 
        !            38:  *     SCSI-CAM system, storing the results in ip as required
        !            39:  *     by the HDIO_GETGEO ioctl().
        !            40:  *
        !            41:  * Returns : -1 on failure, 0 on success.
        !            42:  *
        !            43:  */
        !            44: 
        !            45: int scsicam_bios_param (Disk *disk, /* SCSI disk */
        !            46:        kdev_t dev,             /* Device major, minor */
        !            47:        int *ip                 /* Heads, sectors, cylinders in that order */) {
        !            48: 
        !            49:     struct buffer_head *bh;
        !            50:     int ret_code;
        !            51:     int size = disk->capacity;
        !            52: 
        !            53:     if (!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024)))
        !            54:        return -1;
        !            55: 
        !            56: #ifdef DEBUG
        !            57:        printk ("scsicam_bios_param : trying existing mapping\n");
        !            58: #endif
        !            59:     ret_code = partsize (bh, (unsigned long) size, (unsigned int *) ip + 2, 
        !            60:        (unsigned int *) ip + 0, (unsigned int *) ip + 1);
        !            61:     brelse (bh);
        !            62: 
        !            63:     if (ret_code == -1) {
        !            64: #ifdef DEBUG
        !            65:        printk ("scsicam_bios_param : trying optimal mapping\n");
        !            66: #endif
        !            67:        ret_code = setsize ((unsigned long) size, (unsigned int *) ip + 2, 
        !            68:            (unsigned int *) ip + 0, (unsigned int *) ip + 1);
        !            69:     }
        !            70: 
        !            71:     return ret_code;
        !            72: }
        !            73: 
        !            74: /*
        !            75:  * Function : static int partsize(struct buffer_head *bh, unsigned long 
        !            76:  *     capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
        !            77:  *
        !            78:  * Purpose : to determine the BIOS mapping used to create the partition
        !            79:  *     table, storing the results in *cyls, *hds, and *secs 
        !            80:  *
        !            81:  * Returns : -1 on failure, 0 on success.
        !            82:  *
        !            83:  */
        !            84: 
        !            85: static int partsize(struct buffer_head *bh, unsigned long capacity,
        !            86:     unsigned int  *cyls, unsigned int *hds, unsigned int *secs) {
        !            87:     struct partition *p, *largest = NULL;
        !            88:     int i, largest_cyl;
        !            89:     int cyl, ext_cyl, end_head, end_cyl, end_sector;
        !            90:     unsigned int logical_end, physical_end, ext_physical_end;
        !            91:     
        !            92: 
        !            93:     if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
        !            94:        for (largest_cyl = -1, p = (struct partition *) 
        !            95:            (0x1BE + bh->b_data), i = 0; i < 4; ++i, ++p) {
        !            96:            if (!p->sys_ind)
        !            97:                continue;
        !            98: #ifdef DEBUG
        !            99:        printk ("scsicam_bios_param : partition %d has system \n",
        !           100:            i);
        !           101: #endif
        !           102:            cyl = p->cyl + ((p->sector & 0xc0) << 2);
        !           103:            if (cyl > largest_cyl) {
        !           104:                largest_cyl = cyl;
        !           105:                largest = p;
        !           106:            }
        !           107:        }
        !           108:     }
        !           109: 
        !           110:     if (largest) {
        !           111:        end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2);
        !           112:        end_head = largest->end_head;
        !           113:        end_sector = largest->end_sector & 0x3f;
        !           114: 
        !           115: #ifdef DEBUG
        !           116:        printk ("scsicam_bios_param : end at h = %d, c = %d, s = %d\n",
        !           117:            end_head, end_cyl, end_sector);
        !           118: #endif
        !           119: 
        !           120:        physical_end =  end_cyl * (end_head + 1) * end_sector +
        !           121:            end_head * end_sector + end_sector;
        !           122: 
        !           123:        /* This is the actual _sector_ number at the end */
        !           124:        logical_end = largest->start_sect + largest->nr_sects;
        !           125: 
        !           126:        /* This is for >1023 cylinders */
        !           127:         ext_cyl= (logical_end-(end_head * end_sector + end_sector))
        !           128:                                         /(end_head + 1) / end_sector;
        !           129:        ext_physical_end = ext_cyl * (end_head + 1) * end_sector +
        !           130:             end_head * end_sector + end_sector;
        !           131: 
        !           132: #ifdef DEBUG
        !           133:        printk("scsicam_bios_param : logical_end=%d physical_end=%d ext_physical_end=%d ext_cyl=%d\n"
        !           134:                        ,logical_end,physical_end,ext_physical_end,ext_cyl);
        !           135: #endif
        !           136: 
        !           137:        if ((logical_end == physical_end) ||
        !           138:            (end_cyl==1023 && ext_physical_end==logical_end)) {
        !           139:            *secs = end_sector;
        !           140:            *hds = end_head + 1;
        !           141:            *cyls = capacity / ((end_head + 1) * end_sector);
        !           142:            return 0;
        !           143:        }
        !           144:        
        !           145: #ifdef DEBUG
        !           146:        printk ("scsicam_bios_param : logical (%u) != physical (%u)\n",
        !           147:            logical_end, physical_end);
        !           148: #endif
        !           149:     }
        !           150:     return -1;
        !           151: }
        !           152: 
        !           153: /*
        !           154:  * Function : static int setsize(unsigned long capacity,unsigned int *cyls,
        !           155:  *     unsigned int *hds, unsigned int *secs);
        !           156:  *
        !           157:  * Purpose : to determine a near-optimal int 0x13 mapping for a
        !           158:  *     SCSI disk in terms of lost space of size capacity, storing
        !           159:  *     the results in *cyls, *hds, and *secs.
        !           160:  *
        !           161:  * Returns : -1 on failure, 0 on success.
        !           162:  *
        !           163:  * Extracted from
        !           164:  *
        !           165:  * WORKING                                                    X3T9.2
        !           166:  * DRAFT                                                        792D
        !           167:  *
        !           168:  *
        !           169:  *                                                        Revision 6
        !           170:  *                                                         10-MAR-94
        !           171:  * Information technology -
        !           172:  * SCSI-2 Common access method
        !           173:  * transport and SCSI interface module
        !           174:  * 
        !           175:  * ANNEX A :
        !           176:  *
        !           177:  * setsize() converts a read capacity value to int 13h
        !           178:  * head-cylinder-sector requirements. It minimizes the value for
        !           179:  * number of heads and maximizes the number of cylinders. This
        !           180:  * will support rather large disks before the number of heads
        !           181:  * will not fit in 4 bits (or 6 bits). This algorithm also
        !           182:  * minimizes the number of sectors that will be unused at the end
        !           183:  * of the disk while allowing for very large disks to be
        !           184:  * accommodated. This algorithm does not use physical geometry. 
        !           185:  */
        !           186: 
        !           187: static int setsize(unsigned long capacity,unsigned int *cyls,unsigned int *hds,
        !           188:     unsigned int *secs) { 
        !           189:     unsigned int rv = 0; 
        !           190:     unsigned long heads, sectors, cylinders, temp; 
        !           191: 
        !           192:     cylinders = 1024L;                 /* Set number of cylinders to max */ 
        !           193:     sectors = 62L;                     /* Maximize sectors per track */ 
        !           194: 
        !           195:     temp = cylinders * sectors;                /* Compute divisor for heads */ 
        !           196:     heads = capacity / temp;           /* Compute value for number of heads */
        !           197:     if (capacity % temp) {             /* If no remainder, done! */ 
        !           198:        heads++;                        /* Else, increment number of heads */ 
        !           199:        temp = cylinders * heads;       /* Compute divisor for sectors */ 
        !           200:        sectors = capacity / temp;      /* Compute value for sectors per
        !           201:                                               track */ 
        !           202:        if (capacity % temp) {          /* If no remainder, done! */ 
        !           203:            sectors++;                  /* Else, increment number of sectors */ 
        !           204:            temp = heads * sectors;     /* Compute divisor for cylinders */
        !           205:            cylinders = capacity / temp;/* Compute number of cylinders */ 
        !           206:        } 
        !           207:     } 
        !           208:     if (cylinders == 0) rv=(unsigned)-1;/* Give error if 0 cylinders */ 
        !           209: 
        !           210:     *cyls = (unsigned int) cylinders;  /* Stuff return values */ 
        !           211:     *secs = (unsigned int) sectors; 
        !           212:     *hds  = (unsigned int) heads; 
        !           213:     return(rv); 
        !           214: } 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.