*** /usr/src/sys/scsi/od.c.PL3 Sun Jun 9 01:54:09 1996 --- /usr/src/sys/scsi/od.c Sun Jun 9 03:42:02 1996 *************** *** 84,89 **** --- 84,122 ---- #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; + }; + + /* scsi mode sense command functions copied from cd.c by Jun Obama */ + 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_get_parms __P((int unit, int flags)); static void odstrategy1 __P((struct buf *)); *************** *** 190,195 **** --- 223,229 ---- { u_int32 unit; struct disk_parms *dp; + struct scsi_mode_sense_data data; /* appended by Jun Obama */ struct scsi_data *od = sc_link->sd; *************** *** 232,237 **** --- 266,303 ---- 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; } *************** *** 882,885 **** --- 948,1008 ---- printf(", FAILURE\n"); 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)); }