📄 ide_drv.c
字号:
/* It is atapi */
pc->drive[pdr->logical_unit_number].protocol = 2;
// PVO 11-26-99 just send reset. don't treat as a command
ide_wr_command(pc, IDE_CMD_SOFT_RESET);
/* reset the drive */
// ide_command(IDE_CMD_SOFT_RESET, pc, pdr->logical_unit_number, 0, 0);
for(i=0;i<6;i++)
{
if(atapi_command(ATAPI_PKT_CMD_TEST_UNIT_READY, pc, pdr->logical_unit_number))
break;
ks_sleep((word)(2*ks_ticks_p_sec()));
}
pc->user_address = (PFBYTE) &buf[0];
if(tc_comparen(((PFBYTE)buf)+54, (PFBYTE)"SL1-02", 6)) /* If a HIMAWARI drive? Jerry*/
{
// ??? Do first time to make sure MC is clear (needed by some LS-120 drives)
ide_command(IDE_CMD_GET_MEDIA_STATUS, pc, pdr->logical_unit_number, 0, 0);
if (ide_command(IDE_CMD_GET_MEDIA_STATUS, pc, pdr->logical_unit_number, 0, 0))
{
if (ide_command(ATAPI_CMD_IDENT, pc, pdr->logical_unit_number, 0, 0))
{
/* capture the media descriptor for the format routine */
switch(pc->drive[pdr->logical_unit_number].medium_type_code=(byte)buf[4]) /* Bytes/ Sectors/ */
{ /* Cyl H Sector Track Capacity */
case 0x30: /* Formatted UHD 963 8 512 32 120Mb */
case 0x31: /* Unformatted UHD 963 8 512 32 120Mb */
case 0x20: /* Unformatted HD 80 2 512 18 1.44Mb*/
case 0x24: /* Formatted HD 80 2 512 18 1.44Mb*/
case 0x26: /* DMF 80 2 512 21 1.7Mb*/
pc->drive[pdr->logical_unit_number].media_descriptor=0xf0;
pc->drive[pdr->logical_unit_number].allocation_unit=0x01;
break;
case 0x22: /* Formatted NEC 77 2 1024 8 1.20Mb*/
case 0x23: /* Formatted Toshiba 80 2 512 15 1.20Mb*/
pc->drive[pdr->logical_unit_number].media_descriptor=0xf9;
pc->drive[pdr->logical_unit_number].allocation_unit=0x01;
break;
case 0x27: /* NEC-DMF 77 2 512 9 720Kb*/
case 0x10: /* Unformatted DD 80 2 512 9 720Kb*/
case 0x11: /* Formatted DD 80 2 512 9 720Kb*/
pc->drive[pdr->logical_unit_number].media_descriptor=0xf9;
pc->drive[pdr->logical_unit_number].allocation_unit=0x02;
break;
default:
return(FALSE);
}
}
}
else
return(FALSE);
} // its not a Himawari drive is it a CDROM?
else
{
/* CDROM JERRY START */
if((to_WORD((byte *) &buf[0])&0xdf03)==0x8500)
{
pc->drive[pdr->logical_unit_number].media_descriptor=0xef;
pc->drive[pdr->logical_unit_number].CMD_DRQ_type=(byte)(to_WORD((byte *) &buf[0])&0x60);
}
else
return(FALSE);
/* CDROM JERRY STOP */
}
}
else
#endif /* (IDE_USE_ATAPI) */
return(FALSE);
}
else
{
// BUG BUG - In CDFS system we should d diagnostics here.
pc->drive[pdr->logical_unit_number].media_descriptor=0xf8; /* assume hard disk media */
}
pc->drive[pdr->logical_unit_number].num_cylinders = to_WORD((byte *) &buf[1]);
heads = (byte) (to_WORD((byte *) &buf[3]));
sectors = (byte)(to_WORD((byte *) &buf[6]));
pc->drive[pdr->logical_unit_number].max_multiple = (byte) (to_WORD((byte *) &buf[47]) & 0xff);
if (to_WORD((byte *) &buf[49]) & 0x200)
{
pc->drive[pdr->logical_unit_number].supports_lba = TRUE;
/* Get highword low word of highest lba */
ltemp = to_WORD((byte *) &buf[61]);
ltemp <<= 16;
ltemp += to_WORD((byte *) &buf[60]);
ltemp2 = (dword) pc->drive[pdr->logical_unit_number].num_cylinders;
ltemp2 = (dword) (ltemp2 * heads);
ltemp2 = (dword) (ltemp2 * sectors);
tm_printf("lba fields 60:61 yield %ld h*c*n yield %ld\n", (dword)ltemp, (dword) ltemp2);
pc->drive[pdr->logical_unit_number].total_lba = ltemp;
}
else
{
pc->drive[pdr->logical_unit_number].supports_lba = FALSE;
pc->drive[pdr->logical_unit_number].total_lba = 0;
}
/* Our local view of the drive for block to track::sector::head xlations */
pc->drive[pdr->logical_unit_number].num_heads = heads;
pc->drive[pdr->logical_unit_number].sec_p_track = sectors;
pc->drive[pdr->logical_unit_number].sec_p_cyl = (word) heads;
pc->drive[pdr->logical_unit_number].sec_p_cyl = (word) (pc->drive[pdr->logical_unit_number].sec_p_cyl * sectors);
#if (IDE_USE_ATAPI)
/* If it's an ATAPI IDE drive enable media status notification */
if (pc->drive[pdr->logical_unit_number].protocol == 2)
ide_set_features(pc, pdr->logical_unit_number, 0x95, 0);
#endif
#if (USE_SETPARMS)
#if (IDE_USE_ATAPI)
/* Initialize drive parms (on hard drives only, not ATAPI drives) */
if (pc->drive[pdr->logical_unit_number].protocol != 2) /* if not ATAPI drive: */
#endif
if (!ide_command_setparms(pc, pdr->logical_unit_number, heads, sectors))
{
return(FALSE);
}
#endif
/* 11-10-2000 - New code. Only do SETM on open. We had been doing it
on every read & write which caused a cache flush and slowed down io
Thanks to Paul Swan. */
if (pc->drive[pdr->logical_unit_number].max_multiple > 1)
{
if (!ide_command(IDE_CMD_SETM, pc, pdr->logical_unit_number, 0, 0))
{
return(FALSE);
}
}
pc->drive[pdr->logical_unit_number].open_count++; /*CDROM Support Jerry */
return(TRUE);
}
/* Read/write function: */
BOOLEAN ide_io(int driveno, dword sector, void *buffer, word count, BOOLEAN reading) /*__fn__*/
{
BOOLEAN ret_val;
PIDE_CONTROLLER pc;
DDRIVE *pdr;
pdr = pc_drno_to_drive_struct(driveno);
if (!pdr)
return(FALSE);
pc = &controller_s[pdr->controller_number];
if (!count || !pc) /* Must have a count */
return(FALSE);
ret_val = FALSE;
/* Set up a counter for data transfer (See ide_isr) */
pc->sectors_remaining = count;
// if (op == ERASING)
// {
// ret_val = ide_command(IDE_CMD_ERASES, pc, pdr->logical_unit_number, sector, count);
// }
if (reading)
{
pc->user_address = (PFBYTE) buffer;
/* Use read multiple command */
if ((count > 1) && (pc->drive[pdr->logical_unit_number].max_multiple > 1))
{
/* Call set multiple */
ret_val = ide_command_read_multiple(pc, pdr->logical_unit_number, sector, count);
if (!ret_val)
{
/* Set up a counter for data transfer (See ide_isr) */
pc->sectors_remaining = count;
goto non_multiple_read;
}
}
else
{
non_multiple_read:
do
{
pc->block_size = 1;
ret_val = ide_command(IDE_CMD_READS, pc, pdr->logical_unit_number, sector, count);
if (!ret_val)
{
break; /* Break out of do loop */
}
} while(!ret_val);
}
}
else // WRITING
{
pc->user_address = (PFBYTE) buffer;
if ( (count > 1) && (pc->drive[pdr->logical_unit_number].max_multiple > 1))
{
/* Try write multiple. */
ret_val = ide_command_write_multiple(pc, pdr->logical_unit_number, sector, count);
if (!ret_val)
{
pc->sectors_remaining = count;
goto non_multiple_write;
}
}
else
{
non_multiple_write:
pc->block_size = 1;
ret_val = ide_command(IDE_CMD_WRITES, pc, pdr->logical_unit_number, sector, count);
}
}
return(ret_val);
}
static BOOLEAN ide_command(byte command, PIDE_CONTROLLER pc, int logical_unit_number, dword blockno, word nblocks)
{
ide_clear_voregs(pc); /* Clear virtual output registers */
/* Call ide_rdwr_setup to set transfer addresses, sector_count, sector_number,
cylinder_low, cylinder_hi and drive_head */
if ((command == IDE_CMD_ERASES) ||
(command == IDE_CMD_READS) ||
(command == IDE_CMD_READM) ||
(command == IDE_CMD_WRITEM_NE) ||
(command == IDE_CMD_WRITEM) ||
(command == IDE_CMD_WRITES_NE) ||
(command == IDE_CMD_WRITES) )
{
if (!ide_rdwr_setup(pc, logical_unit_number, blockno, nblocks))
return(FALSE);
pc->timer = (word)TIMEOUT_RDWR;
}
else
{
pc->timer = (word)TIMEOUT_TYPICAL;
}
pc->vo_drive_head |= 0x20; /* Bit five is always one */
if (logical_unit_number) /* Bit four is drive (1 or 0) */
pc->vo_drive_head |= 0x10; /* select device 1 (slave) */
if (command == IDE_CMD_ERASES) /* Erase sets bit 7 */
pc->vo_drive_head |= 0x80;
if (command == IDE_CMD_SETM)
{
pc->block_size = pc->drive[logical_unit_number].max_multiple;
pc->vo_sector_count = pc->block_size;
}
/* 11-10-2000 - New code. Since we don't call SETM on each WRITEM or
READM we must set block size now on the READM, WRITEM calls */
if ((command == IDE_CMD_READM)||
(command == IDE_CMD_WRITEM))
{
pc->block_size = pc->drive[logical_unit_number].max_multiple;
}
pc->vo_command = command;
/* Call the processing routine */
return(ide_do_command(pc));
}
#if (IDE_USE_ATAPI)
BOOLEAN atapi_command(byte command, PIDE_CONTROLLER pc, int logical_unit_number)
{
ide_clear_voregs(pc); /* Clear virtual output registers */
/* Call ide_rdwr_setup to set transfer addresses, sector_count, sector_number,
cylinder_low, cylinder_hi and drive_head */
if(command==ATAPI_PKT_CMD_FORMAT_UNIT)
pc->timer=(word)TIMEOUT_FORMAT;
else
pc->timer = (word)TIMEOUT_TYPICAL;
pc->vo_drive_head |= 0x20; /* Bit five is always one */
if (logical_unit_number) /* Bit four is drive (1 or 0) */
pc->vo_drive_head |= 0x10; /* select device 1 (slave) */
pc->vo_command = command;
/* Call the processing routine */
return(ide_do_command(pc));
}
#endif /* #if (IDE_USE_ATAPI) */
/* ........................................................................
.... End Device driver external interface routines. .......
.......................................................................*/
#if (IDE_USE_SET_FEATURES || IDE_USE_ATAPI)
static BOOLEAN ide_set_features(PIDE_CONTROLLER pc, int logical_unit_number, byte feature, byte config) /* __fn__ */
{
ide_clear_voregs(pc); /* Clear virtual output registers */
if (logical_unit_number) /* Bit four is drive (1 or 0) */
pc->vo_drive_head |= 0x10; /* select device 1 (slave) */
pc->vo_feature = feature;
pc->vo_sector_count = config;
pc->vo_command = IDE_CMD_SETF;
pc->timer = (word)TIMEOUT_TYPICAL;
/* Call the processing routine */
return(ide_do_command(pc));
}
#endif
//DM: commented out conditional to re-enable. Put back conditional if
// routine really is no good for CDROM
//#ifndef CDFS_ONLY
/* Command execution routines. */
/* ide_command_diags - Execute drive diagnostics
*
*
*
* Returns:
* TRUE if the drive diagnostic succeeded else FALSE.
*
* This routine execute a diagnostic request. If the diagnostic succeeds
* it returns TRUE otherwise it returns FALSE.
*
* called by: ide_drive_init
*
* This routine is portable
*
*/
static BOOLEAN ide_command_diags(PIDE_CONTROLLER pc) /* __fn__ */
{
ide_clear_voregs(pc); /* Clear virtual output registers */
pc->vo_command = IDE_CMD_DIAG; /* Command */
pc->timer = (word)TIMEOUT_DIAG;
return(ide_do_command(pc));
}
//DM: commented out conditional to re-enable
//#endif // CDFS_ONLY
/* ide_command_setparms - Set drive parameters
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -