int sub_select( ataio_t *ata, int dev ) { unsigned char dev75; unsigned char status; // determine value of Device (Drive/Head) register bits 7 and 5 dev75 = 0; // normal value if ( ata->reg_incompat_flags & REG_INCOMPAT_DEVREG ) dev75 = CB_DH_OBSOLETE; // obsolete value // PAY ATTENTION HERE // The caller may want to issue a command to a device that doesn't // exist (for example, Exec Dev Diag), so if we see this, // just select that device, skip all status checking and return. // We assume the caller knows what they are doing! if ( ata->reg_config_info[ dev ] < REG_CONFIG_TYPE_ATA ) { // select the device and return pio_outbyte( CB_DH, ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) | dev75 ); ATA_DELAY(); return 0; } // The rest of this is the normal ATA stuff for device selection // and we don't expect the caller to be selecting a device that // does not exist. // We don't know which drive is currently selected but we should // wait BSY=0 and DRQ=0. Normally both BSY=0 and DRQ=0 // unless something is very wrong! trc_llt( 0, 0, TRC_LLT_PNBSY ); while ( 1 ) { status = pio_inbyte( CB_STAT ); if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) == 0 ) break; if ( tmr_chk_timeout() ) { trc_llt( 0, 0, TRC_LLT_TOUT ); reg_cmd_info.to = 1; reg_cmd_info.ec = 11; trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR ); reg_cmd_info.st2 = status; reg_cmd_info.as2 = pio_inbyte( CB_ASTAT ); reg_cmd_info.er2 = pio_inbyte( CB_ERR ); reg_cmd_info.sc2 = pio_inbyte( CB_SC ); reg_cmd_info.sn2 = pio_inbyte( CB_SN ); reg_cmd_info.cl2 = pio_inbyte( CB_CL ); reg_cmd_info.ch2 = pio_inbyte( CB_CH ); reg_cmd_info.dh2 = pio_inbyte( CB_DH ); return 1; } } // Here we select the drive we really want to work with by // setting the DEV bit in the Drive/Head register. pio_outbyte( CB_DH, ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) | dev75 ); ATA_DELAY(); // Wait for the selected device to have BSY=0 and DRQ=0. // Normally the drive should be in this state unless // something is very wrong (or initial power up is still in // progress). trc_llt( 0, 0, TRC_LLT_PNBSY ); while ( 1 ) { status = pio_inbyte( CB_STAT ); if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) == 0 ) break; if ( tmr_chk_timeout() ) { trc_llt( 0, 0, TRC_LLT_TOUT ); reg_cmd_info.to = 1; reg_cmd_info.ec = 12; trc_llt( 0, reg_cmd_info.ec, TRC_LLT_ERROR ); reg_cmd_info.st2 = status; reg_cmd_info.as2 = pio_inbyte( CB_ASTAT ); reg_cmd_info.er2 = pio_inbyte( CB_ERR ); reg_cmd_info.sc2 = pio_inbyte( CB_SC ); reg_cmd_info.sn2 = pio_inbyte( CB_SN ); reg_cmd_info.cl2 = pio_inbyte( CB_CL ); reg_cmd_info.ch2 = pio_inbyte( CB_CH ); reg_cmd_info.dh2 = pio_inbyte( CB_DH ); return 1; } } // All done. The return values of this function are described in // ATAIO.H. if ( reg_cmd_info.ec ) return 1; return 0; }
int sub_select( int dev ) { unsigned char status; // PAY ATTENTION HERE // The caller may want to issue a command to a device that doesn't // exist (for example, Exec Dev Diag), so if we see this, // just select that device, skip all status checking and return. // We assume the caller knows what they are doing! if ( reg_config_info[ dev ] < REG_CONFIG_TYPE_ATA ) { // select the device and return pio_outbyte( CB_DH, dev ? CB_DH_DEV1 : CB_DH_DEV0 ); delay(4); return 0; } // The rest of this is the normal ATA stuff for device selection // and we don't expect the caller to be selecting a device that // does not exist. // We don't know which drive is currently selected but we should // wait for it to be not BUSY. Normally it will be not BUSY // unless something is very wrong! while ( 1 ) { status = pio_inbyte( CB_STAT ); if ( ( status & CB_STAT_BSY ) == 0 ) break; if ( tmr_chk_timeout() ) { reg_cmd_info.to = 1; reg_cmd_info.ec = 11; reg_cmd_info.st2 = status; reg_cmd_info.as2 = pio_inbyte( CB_ASTAT ); reg_cmd_info.er2 = pio_inbyte( CB_ERR ); reg_cmd_info.sc2 = pio_inbyte( CB_SC ); reg_cmd_info.sn2 = pio_inbyte( CB_SN ); reg_cmd_info.cl2 = pio_inbyte( CB_CL ); reg_cmd_info.ch2 = pio_inbyte( CB_CH ); reg_cmd_info.dh2 = pio_inbyte( CB_DH ); return 1; } } // Here we select the drive we really want to work with by // putting 0xA0 or 0xB0 in the Drive/Head register (1f6). pio_outbyte( CB_DH, dev ? CB_DH_DEV1 : CB_DH_DEV0 ); delay(4); // If the selected device is an ATA device, // wait for it to have READY and SEEK COMPLETE // status. Normally the drive should be in this state unless // something is very wrong (or initial power up is still in // progress). For any other type of device, just wait for // BSY=0 and assume the caller knows what they are doing. while ( 1 ) { status = pio_inbyte( CB_STAT ); if ( reg_config_info[ dev ] == REG_CONFIG_TYPE_ATA ) { if ( ( status & ( CB_STAT_BSY | CB_STAT_RDY | CB_STAT_SKC ) ) == ( CB_STAT_RDY | CB_STAT_SKC ) ) break; } else { if ( ( status & CB_STAT_BSY ) == 0 ) break; } if ( tmr_chk_timeout() ) { reg_cmd_info.to = 1; reg_cmd_info.ec = 12; reg_cmd_info.st2 = status; reg_cmd_info.as2 = pio_inbyte( CB_ASTAT ); reg_cmd_info.er2 = pio_inbyte( CB_ERR ); reg_cmd_info.sc2 = pio_inbyte( CB_SC ); reg_cmd_info.sn2 = pio_inbyte( CB_SN ); reg_cmd_info.cl2 = pio_inbyte( CB_CL ); reg_cmd_info.ch2 = pio_inbyte( CB_CH ); reg_cmd_info.dh2 = pio_inbyte( CB_DH ); return 1; } } // All done. The return values of this function are described in // ATAIO.H. if ( reg_cmd_info.ec ) return 1; return 0; }