Annotation of qemu/roms/openbios/arch/ppc/mol/osi-scsi.c, revision 1.1.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.