Annotation of qemu/roms/openbios/arch/ppc/mol/osi-scsi.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *   Creation Date: <2003/12/11 21:23:54 samuel>
        !             3:  *   Time-stamp: <2004/01/07 19:38:45 samuel>
        !             4:  *
        !             5:  *     <osi-scsi.c>
        !             6:  *
        !             7:  *     SCSI device node
        !             8:  *
        !             9:  *   Copyright (C) 2003, 2004 Samuel Rydh ([email protected])
        !            10:  *
        !            11:  *   This program is free software; you can redistribute it and/or
        !            12:  *   modify it under the terms of the GNU General Public License
        !            13:  *   version 2
        !            14:  *
        !            15:  */
        !            16: 
        !            17: #include "config.h"
        !            18: #include "libopenbios/bindings.h"
        !            19: #include "mol/mol.h"
        !            20: #include "scsi_sh.h"
        !            21: #include "osi_calls.h"
        !            22: 
        !            23: #define MAX_TARGETS    32
        !            24: 
        !            25: typedef struct {
        !            26:        int             probed;
        !            27:        int             valid;          /* a useable device found */
        !            28: 
        !            29:        int             is_cd;
        !            30:        int             blocksize;
        !            31: } target_info_t;
        !            32: 
        !            33: static target_info_t   scsi_devs[ MAX_TARGETS ];
        !            34: 
        !            35: typedef struct {
        !            36:        int             target;
        !            37:        target_info_t   *info;
        !            38: } instance_data_t;
        !            39: 
        !            40: 
        !            41: DECLARE_NODE( scsi, INSTALL_OPEN, sizeof(instance_data_t),
        !            42:              "/pci/pci-bridge/mol-scsi/sd", "/mol/mol-scsi/sd" );
        !            43: 
        !            44: 
        !            45: static int
        !            46: scsi_cmd_( instance_data_t *sd, const char *cmd, int cmdlen, char *dest,
        !            47:           int len, int prelen, int postlen )
        !            48: {
        !            49:        char prebuf[4096], postbuf[4096];
        !            50:        scsi_req_t r[2];        /* the [2] is a hack to get space for the sg-list */
        !            51:        char sb[32];
        !            52: 
        !            53:        /* memset( dest, 0, len ); */
        !            54: 
        !            55:        if( (unsigned int)prelen > sizeof(prebuf) || (unsigned int)postlen > sizeof(postbuf) ) {
        !            56:                printk("bad pre/post len %d %d\n", prelen, postlen );
        !            57:                return 1;
        !            58:        }
        !            59: 
        !            60:        memset( r, 0, sizeof(r[0]) );
        !            61:        r->lun = 0;
        !            62:        r->target = sd->target;
        !            63:        r->is_write = 0;
        !            64:        memcpy( r->cdb, cmd, cmdlen );
        !            65:        r->client_addr = (int)&r;
        !            66:        r->cdb_len = cmdlen;
        !            67:        r->sense[0].base = (int)&sb;
        !            68:        r->sense[0].size = sizeof(sb);
        !            69:        r->size = prelen + len + postlen;
        !            70:        r->n_sg = 3;
        !            71:        r->sglist.n_el = 3;
        !            72:        r->sglist.vec[0].base = (int)prebuf;
        !            73:        r->sglist.vec[0].size = prelen;
        !            74:        r->sglist.vec[1].base = (int)dest;
        !            75:        r->sglist.vec[1].size = len;
        !            76:        r->sglist.vec[2].base = (int)postbuf;
        !            77:        r->sglist.vec[2].size = postlen;
        !            78: 
        !            79:        if( OSI_SCSISubmit((int)&r) ) {
        !            80:                printk("OSI_SCSISubmit: error!\n");
        !            81:                return 1;
        !            82:        }
        !            83:        while( !OSI_SCSIAck() )
        !            84:                OSI_USleep( 10 );
        !            85: 
        !            86:        if( r->adapter_status )
        !            87:                return -1;
        !            88:        if( r->scsi_status )
        !            89:                return ((sb[2] & 0xf) << 16) | (sb[12] << 8) | sb[13];
        !            90:        return 0;
        !            91: }
        !            92: 
        !            93: static int
        !            94: scsi_cmd( instance_data_t *sd, const char *cmd, int cmdlen )
        !            95: {
        !            96:        return scsi_cmd_( sd, cmd, cmdlen, NULL, 0, 0, 0 );
        !            97: }
        !            98: 
        !            99: /* ( buf blk nblks -- actual ) */
        !           100: static void
        !           101: scsi_read_blocks( instance_data_t *sd )
        !           102: {
        !           103:        int nblks = POP();
        !           104:        int blk = POP();
        !           105:        char *dest = (char*)POP();
        !           106:        unsigned char cmd[10];
        !           107:        int len = nblks * sd->info->blocksize;
        !           108: 
        !           109:        memset( dest, 0, len );
        !           110: 
        !           111:        /* printk("READ: blk: %d length %d\n", blk, len ); */
        !           112:        memset( cmd, 0, sizeof(cmd) );
        !           113:        cmd[0] = 0x28; /* READ_10 */
        !           114:        cmd[2] = blk >> 24;
        !           115:        cmd[3] = blk >> 16;
        !           116:        cmd[4] = blk >> 8;
        !           117:        cmd[5] = blk;
        !           118:        cmd[7] = nblks >> 8;
        !           119:        cmd[8] = nblks;
        !           120: 
        !           121:        if( scsi_cmd_(sd, cmd, 10, dest, len, 0, 0) ) {
        !           122:                printk("read: scsi_cmd failed\n");
        !           123:                RET( -1 );
        !           124:        }
        !           125:        PUSH( nblks );
        !           126: }
        !           127: 
        !           128: static int
        !           129: inquiry( instance_data_t *sd )
        !           130: {
        !           131:        char inquiry_cmd[6] = { 0x12, 0, 0, 0, 32, 0 };
        !           132:        char start_stop_unit_cmd[6] = { 0x1b, 0, 0, 0, 1, 0 };
        !           133:        char test_unit_ready_cmd[6] = { 0x00, 0, 0, 0, 0, 0 };
        !           134:        char prev_allow_medium_removal[6] = { 0x1e, 0, 0, 0, 1, 0 };
        !           135:        char set_cd_speed_cmd[12] = { 0xbb, 0, 0xff, 0xff, 0xff, 0xff,
        !           136:                                      0, 0, 0, 0, 0, 0 };
        !           137:        target_info_t *info = &scsi_devs[sd->target];
        !           138:        char ret[32];
        !           139:        int i, sense;
        !           140: 
        !           141:        if( sd->target >= MAX_TARGETS )
        !           142:                return -1;
        !           143:        sd->info = info;
        !           144: 
        !           145:        if( info->probed )
        !           146:                return info->valid ? 0:-1;
        !           147:        info->probed = 1;
        !           148: 
        !           149:        if( (sense=scsi_cmd_(sd, inquiry_cmd, 6, ret, 2, 0, 0)) ) {
        !           150:                if( sense < 0 )
        !           151:                        return -1;
        !           152:                printk("INQUIRY failed\n");
        !           153:                return -1;
        !           154:        }
        !           155: 
        !           156:        /* medium present? */
        !           157:        if( (scsi_cmd(sd, test_unit_ready_cmd, 6) >> 8) == 0x23a ) {
        !           158:                printk("no media\n");
        !           159:                return -1;
        !           160:        }
        !           161: 
        !           162:        info->is_cd = 0;
        !           163:        info->blocksize = 512;
        !           164: 
        !           165:        if( ret[0] == 5 /* CD/DVD */ ) {
        !           166:                info->blocksize = 2048;
        !           167:                info->is_cd = 1;
        !           168: 
        !           169:                scsi_cmd( sd, prev_allow_medium_removal, 6 );
        !           170:                scsi_cmd( sd, set_cd_speed_cmd, 12 );
        !           171:                scsi_cmd( sd, start_stop_unit_cmd, 6 );
        !           172: 
        !           173:        } else if( ret[0] == 0 /* DISK */ ) {
        !           174:                scsi_cmd( sd, test_unit_ready_cmd, 6 );
        !           175:                scsi_cmd( sd, start_stop_unit_cmd, 6 );
        !           176:        } else {
        !           177:                /* don't boot from this device (could be a scanner :-)) */
        !           178:                return -1;
        !           179:        }
        !           180: 
        !           181:        /* wait for spin-up (or whatever) to complete */
        !           182:        for( i=0; ; i++ ) {
        !           183:                if( i > 300 ) {
        !           184:                        printk("SCSI timeout (sense %x)\n", sense );
        !           185:                        return -1;
        !           186:                }
        !           187:                sense = scsi_cmd( sd, test_unit_ready_cmd, 6 );
        !           188:                if( (sense & 0xf0000) == 0x20000 ) {
        !           189:                        OSI_USleep( 10000 );
        !           190:                        continue;
        !           191:                }
        !           192:                break;
        !           193:        }
        !           194: 
        !           195:        info->valid = 1;
        !           196:        return 0;
        !           197: }
        !           198: 
        !           199: /* ( -- success? ) */
        !           200: static void
        !           201: scsi_open( instance_data_t *sd )
        !           202: {
        !           203:        static int once = 0;
        !           204:        phandle_t ph;
        !           205: 
        !           206:        fword("my-unit");
        !           207:        sd->target = POP();
        !           208: 
        !           209:        if( !once ) {
        !           210:                once++;
        !           211:                OSI_SCSIControl( SCSI_CTRL_INIT, 0 );
        !           212:        }
        !           213: 
        !           214:        /* obtiain device information */
        !           215:        if( inquiry(sd) )
        !           216:                RET(0);
        !           217: 
        !           218:        selfword("open-deblocker");
        !           219: 
        !           220:        /* interpose disk-label */
        !           221:        ph = find_dev("/packages/disk-label");
        !           222:        fword("my-args");
        !           223:        PUSH_ph( ph );
        !           224:        fword("interpose");
        !           225: 
        !           226:        PUSH( -1 );
        !           227: }
        !           228: 
        !           229: /* ( -- ) */
        !           230: static void
        !           231: scsi_close( instance_data_t *pb )
        !           232: {
        !           233:        selfword("close-deblocker");
        !           234: }
        !           235: 
        !           236: 
        !           237: /* ( -- bs ) */
        !           238: static void
        !           239: scsi_block_size( instance_data_t *sd )
        !           240: {
        !           241:        PUSH( sd->info->blocksize );
        !           242: }
        !           243: 
        !           244: /* ( -- maxbytes ) */
        !           245: static void
        !           246: scsi_max_transfer( instance_data_t *sd )
        !           247: {
        !           248:        PUSH( 1024*1024 );
        !           249: }
        !           250: 
        !           251: static void
        !           252: scsi_initialize( instance_data_t *sd )
        !           253: {
        !           254:        fword("is-deblocker");
        !           255: }
        !           256: 
        !           257: 
        !           258: NODE_METHODS( scsi ) = {
        !           259:        { NULL,                 scsi_initialize },
        !           260:        { "open",               scsi_open               },
        !           261:        { "close",              scsi_close              },
        !           262:        { "read-blocks",        scsi_read_blocks        },
        !           263:        { "block-size",         scsi_block_size },
        !           264:        { "max-transfer",       scsi_max_transfer       },
        !           265: };
        !           266: 
        !           267: void
        !           268: osiscsi_init( void )
        !           269: {
        !           270:        REGISTER_NODE( scsi );
        !           271: }

unix.superglobalmegacorp.com

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