Annotation of Gnu-Mach/i386/i386at/gpl/linux/scsi/scsicam.c, revision 1.1.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.