Annotation of Gnu-Mach/linux/src/drivers/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 <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.