*** od.c.orig Sun Jun 2 00:20:17 1996 --- od.c Sat Jun 1 23:38:53 1996 *************** *** 71,82 **** --- 71,116 ---- #define ODSETUNIT(DEV, U) \ makedev(major(DEV), dkmakeminor((U), dkslice(DEV), dkpart(DEV))) + /* SCSI Caching page definition by Jun Obama */ + struct scsi_caching_page_data { + u_char page_code; + #define SCSI_CACHING_PAGE_CODE 0x08 + #define SCSI_CACHING_PAGE_PS_CURRENT 0x00 + #define SCSI_CACHING_PAGE_PS_CHANGEABLE 0x40 + #define SCSI_CACHING_PAGE_PS_DEFAULT 0x80 + #define SCSI_CACHING_PAGE_PS_SAVED 0xC0 + u_char param_len; + u_char flags; + #define SCSI_CACHING_PAGE_WCE 0x04 + #define SCSI_CACHING_PAGE_MF 0x02 + #define SCSI_CACHING_PAGE_RCD 0x01 + u_char retention_priorities; + #define SCSI_CACHING_PAGE_DEMAND_READ_RETENTION 0xf0 + #define SCSI_CACHING_PAGE_WRITE_RETENTION 0x0f + u_char disable_prefetch_transfer_len[2]; + u_char min_prefetch[2]; + u_char max_prefetch[2]; + u_char max_prefetch_ceiling[2]; + }; + + /* scsi mode sense data format copied from sd.c by Jun Obama*/ + struct scsi_mode_sense_data { + struct scsi_mode_header header; + struct blk_desc blk_desc; + struct scsi_caching_page_data pages; + }; + static errval od_get_parms __P((int unit, int flags)); + static errval od_get_mode __P((u_int32 unit, struct scsi_mode_sense_data *, u_int32 page)); + static errval od_set_mode __P((u_int32 unit, struct scsi_mode_sense_data *)); + static errval od_set_synchronize_cache_command(u_int32); + static void odstrategy1 __P((struct buf *)); static int od_sense_handler __P((struct scsi_xfer *)); static void odstart __P((u_int32, u_int32)); + struct scsi_data { u_int32 flags; #define ODINIT 0x04 /* device has been init'd */ *************** *** 177,182 **** --- 211,217 ---- { u_int32 unit; struct disk_parms *dp; + struct scsi_mode_sense_data data; struct scsi_data *od = sc_link->sd; *************** *** 219,224 **** --- 254,290 ---- od->flags |= ODINIT; od_registerdev(unit); + /* + * Write Cache Disable routine for DELTIS MOS321 1.60. + * The bug in DELTIS MOS321 1.60 is that unable to control SCSI bus + * when write cache is full. + * appended by Jun Obama + */ + /* get changeable cache information */ + od_get_mode(unit, &data, SCSI_CACHING_PAGE_CODE | SCSI_CACHING_PAGE_PS_CHANGEABLE); + { + u_char chgabl; + int chgflag = 0; + + chgabl = data.pages.flags; + /* get current cache information */ + od_get_mode(unit, &data, SCSI_CACHING_PAGE_CODE); + /* if write cache is changeable to disable, change it */ + if ( chgabl & SCSI_CACHING_PAGE_WCE ) { + data.pages.flags &= ~SCSI_CACHING_PAGE_WCE; + chgflag = 1; + } + /* if read cache is changeable to enable, change it */ + if ( chgabl & SCSI_CACHING_PAGE_RCD ) { + data.pages.flags |= SCSI_CACHING_PAGE_RCD; + chgflag = 1; + } + /* if need, set SCSI drive to changed cache mode */ + if ( chgflag ) { + od_set_mode(unit, &data); + } + } + return 0; } *************** *** 485,491 **** * Check if the device has room for another command */ while (sc_link->opennings) { - /* * there is excess capacity, but a special waits * It'll need the adapter as soon as we clear out of the --- 551,556 ---- *************** *** 502,508 **** return; } dp->b_actf = bp->b_actf; - /* * If the device has become invalid, abort all the * reads and writes until all files have been closed and --- 567,572 ---- *************** *** 713,718 **** --- 777,783 ---- struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit); struct scsi_data *od = sc_link->sd; struct disk_parms *disk_parms = &od->params; + struct scsi_mode_sense scsi_cmd; u_int32 sectors; errval retval; *************** *** 835,837 **** --- 900,961 ---- return SCSIRET_DO_RETRY; } + /* + * Get the requested page into the buffer given + * Copied by Jun Obama from cd.c + */ + static errval + od_get_mode(unit, data, page) + u_int32 unit; + struct scsi_mode_sense_data *data; + u_int32 page; + { + struct scsi_mode_sense scsi_cmd; + errval retval; + + bzero(&scsi_cmd, sizeof(scsi_cmd)); + bzero(data, sizeof(*data)); + scsi_cmd.op_code = MODE_SENSE; + scsi_cmd.page = page; + scsi_cmd.length = sizeof(*data) & 0xff; + retval = scsi_scsi_cmd(SCSI_LINK(&od_switch, unit), + (struct scsi_generic *) &scsi_cmd, + sizeof(scsi_cmd), + (u_char *) data, + sizeof(*data), + OD_RETRIES, + 20000, /* should be immed */ + NULL, + SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT | SCSI_DATA_IN); + return (retval); + } + + /* + * Set the requested page into the buffer given + * Copied by Jun Obama from cd.c + */ + errval + od_set_mode(unit, data) + u_int32 unit; + struct scsi_mode_sense_data *data; + { + struct scsi_mode_select scsi_cmd; + + bzero(&scsi_cmd, sizeof(scsi_cmd)); + scsi_cmd.op_code = MODE_SELECT; + /* scsi_cmd.byte2 |= (SMS_PF | SMS_SP); */ + scsi_cmd.byte2 |= SMS_PF; + scsi_cmd.length = sizeof(*data) & 0xff; + data->header.data_length = 0; + return (scsi_scsi_cmd(SCSI_LINK(&od_switch, unit), + (struct scsi_generic *) &scsi_cmd, + sizeof(scsi_cmd), + (u_char *) data, + sizeof(*data), + OD_RETRIES, + 20000, /* should be immed */ + NULL, + SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT | SCSI_DATA_OUT)); + } + +