Annotation of Gnu-Mach/linux/src/drivers/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 <asm/unaligned.h>
        !            26: #include "scsi.h"
        !            27: #include "hosts.h"
        !            28: #include "sd.h"
        !            29: 
        !            30: static int partsize(struct buffer_head *bh, unsigned long capacity,
        !            31:     unsigned int  *cyls, unsigned int *hds, unsigned int *secs);
        !            32: static int setsize(unsigned long capacity,unsigned int *cyls,unsigned int *hds,
        !            33:     unsigned int *secs);
        !            34: 
        !            35: /*
        !            36:  * Function : int scsicam_bios_param (Disk *disk, int dev, int *ip)
        !            37:  *
        !            38:  * Purpose : to determine the BIOS mapping used for a drive in a 
        !            39:  *     SCSI-CAM system, storing the results in ip as required
        !            40:  *     by the HDIO_GETGEO ioctl().
        !            41:  *
        !            42:  * Returns : -1 on failure, 0 on success.
        !            43:  *
        !            44:  */
        !            45: 
        !            46: int scsicam_bios_param (Disk *disk, /* SCSI disk */
        !            47:        kdev_t dev,             /* Device major, minor */
        !            48:        int *ip                 /* Heads, sectors, cylinders in that order */) {
        !            49: 
        !            50:     struct buffer_head *bh;
        !            51:     int ret_code;
        !            52:     int size = disk->capacity;
        !            53:     unsigned long temp_cyl;
        !            54: 
        !            55:     if (!(bh = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, 1024)))
        !            56:        return -1;
        !            57: 
        !            58:     /* try to infer mapping from partition table */
        !            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:        /* pick some standard mapping with at most 1024 cylinders,
        !            65:           and at most 62 sectors per track - this works up to
        !            66:           7905 MB */
        !            67:        ret_code = setsize ((unsigned long) size, (unsigned int *) ip + 2, 
        !            68:            (unsigned int *) ip + 0, (unsigned int *) ip + 1);
        !            69:     }
        !            70: 
        !            71:     /* if something went wrong, then apparently we have to return
        !            72:        a geometry with more than 1024 cylinders */
        !            73:     if (ret_code || ip[0] > 255 || ip[1] > 63) {
        !            74:         ip[0] = 64;
        !            75:         ip[1] = 32;
        !            76:         temp_cyl = size / (ip[0] * ip[1]);
        !            77:         if (temp_cyl > 65534) {
        !            78:              ip[0] = 255;
        !            79:              ip[1] = 63;
        !            80:         }
        !            81:         ip[2] = size / (ip[0] * ip[1]);
        !            82:     }
        !            83: 
        !            84:     return 0;
        !            85: }
        !            86: 
        !            87: /*
        !            88:  * Function : static int partsize(struct buffer_head *bh, unsigned long 
        !            89:  *     capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
        !            90:  *
        !            91:  * Purpose : to determine the BIOS mapping used to create the partition
        !            92:  *     table, storing the results in *cyls, *hds, and *secs 
        !            93:  *
        !            94:  * Returns : -1 on failure, 0 on success.
        !            95:  *
        !            96:  */
        !            97: 
        !            98: static int partsize(struct buffer_head *bh, unsigned long capacity,
        !            99:     unsigned int  *cyls, unsigned int *hds, unsigned int *secs) {
        !           100:     struct partition *p, *largest = NULL;
        !           101:     int i, largest_cyl;
        !           102:     int cyl, ext_cyl, end_head, end_cyl, end_sector;
        !           103:     unsigned int logical_end, physical_end, ext_physical_end;
        !           104:     
        !           105: 
        !           106:     if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
        !           107:        for (largest_cyl = -1, p = (struct partition *) 
        !           108:            (0x1BE + bh->b_data), i = 0; i < 4; ++i, ++p) {
        !           109:            if (!p->sys_ind)
        !           110:                continue;
        !           111: #ifdef DEBUG
        !           112:        printk ("scsicam_bios_param : partition %d has system \n",
        !           113:            i);
        !           114: #endif
        !           115:            cyl = p->cyl + ((p->sector & 0xc0) << 2);
        !           116:            if (cyl > largest_cyl) {
        !           117:                largest_cyl = cyl;
        !           118:                largest = p;
        !           119:            }
        !           120:        }
        !           121:     }
        !           122: 
        !           123:     if (largest) {
        !           124:        end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2);
        !           125:        end_head = largest->end_head;
        !           126:        end_sector = largest->end_sector & 0x3f;
        !           127: 
        !           128:         if( end_head + 1 == 0 || end_sector == 0 ) return -1;
        !           129: 
        !           130: #ifdef DEBUG
        !           131:        printk ("scsicam_bios_param : end at h = %d, c = %d, s = %d\n",
        !           132:            end_head, end_cyl, end_sector);
        !           133: #endif
        !           134: 
        !           135:        physical_end =  end_cyl * (end_head + 1) * end_sector +
        !           136:            end_head * end_sector + end_sector;
        !           137: 
        !           138:        /* This is the actual _sector_ number at the end */
        !           139:        logical_end = get_unaligned(&largest->start_sect)
        !           140:                        + get_unaligned(&largest->nr_sects);
        !           141: 
        !           142:        /* This is for >1023 cylinders */
        !           143:         ext_cyl= (logical_end-(end_head * end_sector + end_sector))
        !           144:                                         /(end_head + 1) / end_sector;
        !           145:        ext_physical_end = ext_cyl * (end_head + 1) * end_sector +
        !           146:             end_head * end_sector + end_sector;
        !           147: 
        !           148: #ifdef DEBUG
        !           149:        printk("scsicam_bios_param : logical_end=%d physical_end=%d ext_physical_end=%d ext_cyl=%d\n"
        !           150:                        ,logical_end,physical_end,ext_physical_end,ext_cyl);
        !           151: #endif
        !           152: 
        !           153:        if ((logical_end == physical_end) ||
        !           154:            (end_cyl==1023 && ext_physical_end==logical_end)) {
        !           155:            *secs = end_sector;
        !           156:            *hds = end_head + 1;
        !           157:            *cyls = capacity / ((end_head + 1) * end_sector);
        !           158:            return 0;
        !           159:        }
        !           160:        
        !           161: #ifdef DEBUG
        !           162:        printk ("scsicam_bios_param : logical (%u) != physical (%u)\n",
        !           163:            logical_end, physical_end);
        !           164: #endif
        !           165:     }
        !           166:     return -1;
        !           167: }
        !           168: 
        !           169: /*
        !           170:  * Function : static int setsize(unsigned long capacity,unsigned int *cyls,
        !           171:  *     unsigned int *hds, unsigned int *secs);
        !           172:  *
        !           173:  * Purpose : to determine a near-optimal int 0x13 mapping for a
        !           174:  *     SCSI disk in terms of lost space of size capacity, storing
        !           175:  *     the results in *cyls, *hds, and *secs.
        !           176:  *
        !           177:  * Returns : -1 on failure, 0 on success.
        !           178:  *
        !           179:  * Extracted from
        !           180:  *
        !           181:  * WORKING                                                    X3T9.2
        !           182:  * DRAFT                                                        792D
        !           183:  *
        !           184:  *
        !           185:  *                                                        Revision 6
        !           186:  *                                                         10-MAR-94
        !           187:  * Information technology -
        !           188:  * SCSI-2 Common access method
        !           189:  * transport and SCSI interface module
        !           190:  * 
        !           191:  * ANNEX A :
        !           192:  *
        !           193:  * setsize() converts a read capacity value to int 13h
        !           194:  * head-cylinder-sector requirements. It minimizes the value for
        !           195:  * number of heads and maximizes the number of cylinders. This
        !           196:  * will support rather large disks before the number of heads
        !           197:  * will not fit in 4 bits (or 6 bits). This algorithm also
        !           198:  * minimizes the number of sectors that will be unused at the end
        !           199:  * of the disk while allowing for very large disks to be
        !           200:  * accommodated. This algorithm does not use physical geometry. 
        !           201:  */
        !           202: 
        !           203: static int setsize(unsigned long capacity,unsigned int *cyls,unsigned int *hds,
        !           204:     unsigned int *secs) { 
        !           205:     unsigned int rv = 0; 
        !           206:     unsigned long heads, sectors, cylinders, temp; 
        !           207: 
        !           208:     cylinders = 1024L;                 /* Set number of cylinders to max */ 
        !           209:     sectors = 62L;                     /* Maximize sectors per track */ 
        !           210: 
        !           211:     temp = cylinders * sectors;                /* Compute divisor for heads */ 
        !           212:     heads = capacity / temp;           /* Compute value for number of heads */
        !           213:     if (capacity % temp) {             /* If no remainder, done! */ 
        !           214:        heads++;                        /* Else, increment number of heads */ 
        !           215:        temp = cylinders * heads;       /* Compute divisor for sectors */ 
        !           216:        sectors = capacity / temp;      /* Compute value for sectors per
        !           217:                                               track */ 
        !           218:        if (capacity % temp) {          /* If no remainder, done! */ 
        !           219:            sectors++;                  /* Else, increment number of sectors */ 
        !           220:            temp = heads * sectors;     /* Compute divisor for cylinders */
        !           221:            cylinders = capacity / temp;/* Compute number of cylinders */ 
        !           222:        } 
        !           223:     } 
        !           224:     if (cylinders == 0) rv=(unsigned)-1;/* Give error if 0 cylinders */ 
        !           225: 
        !           226:     *cyls = (unsigned int) cylinders;  /* Stuff return values */ 
        !           227:     *secs = (unsigned int) sectors; 
        !           228:     *hds  = (unsigned int) heads; 
        !           229:     return(rv); 
        !           230: } 

unix.superglobalmegacorp.com

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