Annotation of linux/kernel/blk_drv/hd.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  linux/kernel/hd.c
                      3:  *
                      4:  *  (C) 1991  Linus Torvalds
                      5:  */
                      6: 
                      7: /*
                      8:  * This is the low-level hd interrupt support. It traverses the
                      9:  * request-list, using interrupts to jump between functions. As
                     10:  * all the functions are called within interrupts, we may not
                     11:  * sleep. Special care is recommended.
                     12:  */
                     13: 
                     14: #include <linux/config.h>
                     15: #include <linux/sched.h>
                     16: #include <linux/fs.h>
                     17: #include <linux/kernel.h>
                     18: #include <linux/hdreg.h>
                     19: #include <asm/system.h>
                     20: #include <asm/io.h>
                     21: #include <asm/segment.h>
                     22: 
                     23: #define MAJOR_NR 3
                     24: #include "blk.h"
                     25: 
                     26: /* Max read/write errors/sector */
                     27: #define MAX_ERRORS     5
                     28: #define MAX_HD         2
                     29: 
                     30: /*
                     31:  *  This struct defines the HD's and their types.
                     32:  */
                     33: struct hd_i_struct {
                     34:        int head,sect,cyl,wpcom,lzone,ctl;
                     35:        };
                     36: #ifdef HD_TYPE
                     37: struct hd_i_struct hd_info[] = { HD_TYPE };
                     38: #define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct)))
                     39: #else
                     40: struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
                     41: static int NR_HD = 0;
                     42: #endif
                     43: 
                     44: static struct hd_struct {
                     45:        long start_sect;
                     46:        long nr_sects;
                     47: } hd[5*MAX_HD]={{0,0},};
                     48: 
                     49: #define port_read(port,buf,nr) \
                     50: __asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di")
                     51: 
                     52: #define port_write(port,buf,nr) \
                     53: __asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")
                     54: 
                     55: extern void hd_interrupt(void);
                     56: 
                     57: /* This may be used only once, enforced by 'static int callable' */
                     58: int sys_setup(void * BIOS)
                     59: {
                     60:        static int callable = 1;
                     61:        int i,drive;
                     62:        struct partition *p;
                     63:        struct buffer_head * bh;
                     64: 
                     65:        if (!callable)
                     66:                return -1;
                     67:        callable = 0;
                     68: #ifndef HD_TYPE
                     69:        for (drive=0 ; drive<2 ; drive++) {
                     70:                hd_info[drive].cyl = *(unsigned short *) BIOS;
                     71:                hd_info[drive].head = *(unsigned char *) (2+BIOS);
                     72:                hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
                     73:                hd_info[drive].ctl = *(unsigned char *) (8+BIOS);
                     74:                hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
                     75:                hd_info[drive].sect = *(unsigned char *) (14+BIOS);
                     76:                BIOS += 16;
                     77:        }
                     78:        if (hd_info[1].cyl)
                     79:                NR_HD=2;
                     80:        else
                     81:                NR_HD=1;
                     82: #endif
                     83:        for (i=0 ; i<NR_HD ; i++) {
                     84:                hd[i*5].start_sect = 0;
                     85:                hd[i*5].nr_sects = hd_info[i].head*
                     86:                                hd_info[i].sect*hd_info[i].cyl;
                     87:        }
                     88:        for (drive=0 ; drive<NR_HD ; drive++) {
                     89:                if (!(bh = bread(0x300 + drive*5,0))) {
                     90:                        printk("Unable to read partition table of drive %d\n\r",
                     91:                                drive);
                     92:                        panic("");
                     93:                }
                     94:                if (bh->b_data[510] != 0x55 || (unsigned char)
                     95:                    bh->b_data[511] != 0xAA) {
                     96:                        printk("Bad partition table on drive %d\n\r",drive);
                     97:                        panic("");
                     98:                }
                     99:                p = 0x1BE + (void *)bh->b_data;
                    100:                for (i=1;i<5;i++,p++) {
                    101:                        hd[i+5*drive].start_sect = p->start_sect;
                    102:                        hd[i+5*drive].nr_sects = p->nr_sects;
                    103:                }
                    104:                brelse(bh);
                    105:        }
                    106:        printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
                    107:        mount_root();
                    108:        return (0);
                    109: }
                    110: 
                    111: static int controller_ready(void)
                    112: {
                    113:        int retries=1000;
                    114: 
                    115:        while (--retries && (inb(HD_STATUS)&0xc0)!=0x40);
                    116:        return (retries);
                    117: }
                    118: 
                    119: static int win_result(void)
                    120: {
                    121:        int i=inb(HD_STATUS);
                    122: 
                    123:        if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
                    124:                == (READY_STAT | SEEK_STAT))
                    125:                return(0); /* ok */
                    126:        if (i&1) i=inb(HD_ERROR);
                    127:        return (1);
                    128: }
                    129: 
                    130: static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
                    131:                unsigned int head,unsigned int cyl,unsigned int cmd,
                    132:                void (*intr_addr)(void))
                    133: {
                    134:        register int port asm("dx");
                    135: 
                    136:        if (drive>1 || head>15)
                    137:                panic("Trying to write bad sector");
                    138:        if (!controller_ready())
                    139:                panic("HD controller not ready");
                    140:        do_hd = intr_addr;
                    141:        outb(hd_info[drive].ctl,HD_CMD);
                    142:        port=HD_DATA;
                    143:        outb_p(hd_info[drive].wpcom>>2,++port);
                    144:        outb_p(nsect,++port);
                    145:        outb_p(sect,++port);
                    146:        outb_p(cyl,++port);
                    147:        outb_p(cyl>>8,++port);
                    148:        outb_p(0xA0|(drive<<4)|head,++port);
                    149:        outb(cmd,++port);
                    150: }
                    151: 
                    152: static int drive_busy(void)
                    153: {
                    154:        unsigned int i;
                    155: 
                    156:        for (i = 0; i < 100000; i++)
                    157:                if (READY_STAT == (inb(HD_STATUS) & (BUSY_STAT | READY_STAT)))
                    158:                        break;
                    159:        i = inb(HD_STATUS);
                    160:        i &= BUSY_STAT | READY_STAT | SEEK_STAT;
                    161:        if (i == READY_STAT | SEEK_STAT)
                    162:                return(0);
                    163:        printk("HD controller times out\n\r");
                    164:        return(1);
                    165: }
                    166: 
                    167: static void reset_controller(void)
                    168: {
                    169:        int     i;
                    170: 
                    171:        outb(4,HD_CMD);
                    172:        for(i = 0; i < 1000; i++) nop();
                    173:        outb(0,HD_CMD);
                    174:        for(i = 0; i < 10000 && drive_busy(); i++) /* nothing */;
                    175:        if (drive_busy())
                    176:                printk("HD-controller still busy\n\r");
                    177:        if((i = inb(ERR_STAT)) != 1)
                    178:                printk("HD-controller reset failed: %02x\n\r",i);
                    179: }
                    180: 
                    181: static void redo_hd_request(void)
                    182: {
                    183:        do_hd = NULL;
                    184:        do_hd_request();
                    185: }
                    186: 
                    187: static void reset_hd(int nr)
                    188: {
                    189:        reset_controller();
                    190:        hd_out(nr,hd_info[nr].sect,hd_info[nr].sect,hd_info[nr].head-1,
                    191:                hd_info[nr].cyl,WIN_SPECIFY,&redo_hd_request);
                    192: }
                    193: 
                    194: void unexpected_hd_interrupt(void)
                    195: {
                    196:        printk("Unexpected HD interrupt\n\r");
                    197: }
                    198: 
                    199: static void bad_rw_intr(void)
                    200: {
                    201:        int i = CURRENT_DEV;
                    202: 
                    203:        if (CURRENT->errors++ >= MAX_ERRORS)
                    204:                end_request(0);
                    205:        reset_hd(i);
                    206: }
                    207: 
                    208: static void read_intr(void)
                    209: {
                    210:        if (win_result()) {
                    211:                bad_rw_intr();
                    212:                return;
                    213:        }
                    214:        port_read(HD_DATA,CURRENT->buffer,256);
                    215:        CURRENT->errors = 0;
                    216:        CURRENT->buffer += 512;
                    217:        CURRENT->sector++;
                    218:        if (--CURRENT->nr_sectors)
                    219:                return;
                    220:        end_request(1);
                    221:        do_hd_request();
                    222: }
                    223: 
                    224: static void write_intr(void)
                    225: {
                    226:        if (win_result()) {
                    227:                bad_rw_intr();
                    228:                return;
                    229:        }
                    230:        if (--CURRENT->nr_sectors) {
                    231:                CURRENT->sector++;
                    232:                CURRENT->buffer += 512;
                    233:                port_write(HD_DATA,CURRENT->buffer,256);
                    234:                return;
                    235:        }
                    236:        end_request(1);
                    237:        do_hd_request();
                    238: }
                    239: 
                    240: void do_hd_request(void)
                    241: {
                    242:        int i,r;
                    243:        unsigned int block,dev;
                    244:        unsigned int sec,head,cyl;
                    245:        unsigned int nsect;
                    246: 
                    247:        INIT_REQUEST;
                    248:        dev = MINOR(CURRENT->dev);
                    249:        block = CURRENT->sector;
                    250:        if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) {
                    251:                end_request(0);
                    252:                goto repeat;
                    253:        }
                    254:        block += hd[dev].start_sect;
                    255:        dev /= 5;
                    256:        __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),
                    257:                "r" (hd_info[dev].sect));
                    258:        __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
                    259:                "r" (hd_info[dev].head));
                    260:        sec++;
                    261:        nsect = CURRENT->nr_sectors;
                    262:        if (CURRENT->cmd == WRITE) {
                    263:                hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
                    264:                for(i=0 ; i<3000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
                    265:                        /* nothing */ ;
                    266:                if (!r) {
                    267:                        reset_hd(CURRENT_DEV);
                    268:                        return;
                    269:                }
                    270:                port_write(HD_DATA,CURRENT->buffer,256);
                    271:        } else if (CURRENT->cmd == READ) {
                    272:                hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
                    273:        } else
                    274:                panic("unknown hd-command");
                    275: }
                    276: 
                    277: void hd_init(void)
                    278: {
                    279:        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
                    280:        set_trap_gate(0x2E,&hd_interrupt);
                    281:        outb_p(inb_p(0x21)&0xfb,0x21);
                    282:        outb(inb_p(0xA1)&0xbf,0xA1);
                    283: }

unix.superglobalmegacorp.com

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