Annotation of Gnu-Mach/linux/src/drivers/scsi/scsicam.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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