1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23/*
24 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#pragma ident	"%Z%%M%	%I%	%E% SMI"
29
30/*
31 * This file contains functions that implement the cache menu commands.
32 */
33#include "global.h"
34#include <sys/time.h>
35#include <sys/resource.h>
36#include <sys/wait.h>
37#include <signal.h>
38#include <string.h>
39#include <sys/fcntl.h>
40#include <sys/stat.h>
41
42#include <sys/dklabel.h>
43
44#include "main.h"
45#include "analyze.h"
46#include "menu.h"
47#include "menu_cache.h"
48#include "param.h"
49#include "misc.h"
50#include "label.h"
51#include "startup.h"
52#include "partition.h"
53#include "prompts.h"
54#include "checkdev.h"
55#include "io.h"
56#include "ctlr_scsi.h"
57#include "auto_sense.h"
58#include "hardware_structs.h"
59
60extern	struct menu_item menu_cache[];
61extern	struct menu_item menu_write_cache[];
62extern	struct menu_item menu_read_cache[];
63
64
65int
66c_cache()
67{
68	cur_menu++;
69	last_menu = cur_menu;
70	run_menu(menu_cache, "CACHE", "cache", 0);
71	cur_menu--;
72	return (0);
73}
74
75int
76ca_write_cache()
77{
78	cur_menu++;
79	last_menu = cur_menu;
80	run_menu(menu_write_cache, "WRITE_CACHE", "write_cache", 0);
81	cur_menu--;
82	return (0);
83}
84
85int
86ca_read_cache()
87{
88	cur_menu++;
89	last_menu = cur_menu;
90	run_menu(menu_read_cache, "READ_CACHE", "read_cache", 0);
91	cur_menu--;
92	return (0);
93}
94
95int
96ca_write_display()
97{
98	struct mode_cache		*page8;
99	struct scsi_ms_header		header;
100	int				status;
101	union {
102		struct mode_cache	page8;
103		char			rawbuf[MAX_MODE_SENSE_SIZE];
104	} u_page8;
105
106	page8 = &u_page8.page8;
107
108	status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
109			MODE_SENSE_PC_CURRENT, (caddr_t)page8,
110			MAX_MODE_SENSE_SIZE, &header);
111
112	if (status == 0) {
113		if (page8->wce) {
114			fmt_print("Write Cache is enabled\n");
115		} else {
116			fmt_print("Write Cache is disabled\n");
117		}
118	} else {
119		err_print("Mode sense failed.\n");
120	}
121	return (0);
122}
123
124int
125ca_write_enable()
126{
127	struct mode_cache		*page8;
128	struct scsi_ms_header		header;
129	int				status;
130	int				length;
131	int				sp_flags;
132	union {
133		struct mode_cache	page8;
134		char			rawbuf[MAX_MODE_SENSE_SIZE];
135	} u_page8;
136
137	page8 = &u_page8.page8;
138
139	status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
140			MODE_SENSE_PC_CHANGEABLE, (caddr_t)page8,
141			MAX_MODE_SENSE_SIZE, &header);
142
143	if (status == 0) {
144		if (page8->wce) {
145			status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
146				MODE_SENSE_PC_SAVED, (caddr_t)page8,
147				MAX_MODE_SENSE_SIZE, &header);
148			if (status != 0) {
149				status = uscsi_mode_sense(cur_file,
150				DAD_MODE_CACHE, MODE_SENSE_PC_CURRENT,
151				(caddr_t)page8, MAX_MODE_SENSE_SIZE, &header);
152			}
153
154			if (status == 0) {
155				length = MODESENSE_PAGE_LEN(page8);
156				sp_flags = MODE_SELECT_PF;
157				if (page8->mode_page.ps) {
158					sp_flags |= MODE_SELECT_SP;
159				} else {
160					err_print("\
161This setting is valid until next reset only. It is not saved permanently.\n");
162				}
163				page8->mode_page.ps = 0;
164				page8->wce = 1;
165				header.mode_header.length = 0;
166				header.mode_header.device_specific = 0;
167				status = uscsi_mode_select(cur_file,
168					DAD_MODE_CACHE, sp_flags,
169					(caddr_t)page8, length, &header);
170				if (status != 0) {
171					err_print("Mode select failed\n");
172					return (0);
173				}
174			}
175		} else {
176			err_print("Write cache setting is not changeable\n");
177		}
178	}
179	if (status != 0) {
180		err_print("Mode sense failed.\n");
181	}
182	return (0);
183}
184
185int
186ca_write_disable()
187{
188	struct mode_cache		*page8;
189	struct scsi_ms_header		header;
190	int				status;
191	int				length;
192	int				sp_flags;
193	union {
194		struct mode_cache	page8;
195		char			rawbuf[MAX_MODE_SENSE_SIZE];
196	} u_page8;
197
198	page8 = &u_page8.page8;
199
200	status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
201			MODE_SENSE_PC_CHANGEABLE, (caddr_t)page8,
202			MAX_MODE_SENSE_SIZE, &header);
203
204	if (status == 0) {
205		if (page8->wce) {
206			status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
207				MODE_SENSE_PC_SAVED, (caddr_t)page8,
208				MAX_MODE_SENSE_SIZE, &header);
209			if (status != 0) {
210				status = uscsi_mode_sense(cur_file,
211				DAD_MODE_CACHE, MODE_SENSE_PC_CURRENT,
212				(caddr_t)page8, MAX_MODE_SENSE_SIZE, &header);
213			}
214
215			if (status == 0) {
216				length = MODESENSE_PAGE_LEN(page8);
217				sp_flags = MODE_SELECT_PF;
218				if (page8->mode_page.ps) {
219					sp_flags |= MODE_SELECT_SP;
220				} else {
221					err_print("\
222This setting is valid until next reset only. It is not saved permanently.\n");
223				}
224				page8->mode_page.ps = 0;
225				page8->wce = 0;
226				header.mode_header.length = 0;
227				header.mode_header.device_specific = 0;
228				status = uscsi_mode_select(cur_file,
229					DAD_MODE_CACHE, sp_flags,
230					(caddr_t)page8, length, &header);
231				if (status != 0) {
232					err_print("Mode select failed\n");
233					return (0);
234				}
235			}
236		} else {
237			err_print("Write cache setting is not changeable\n");
238		}
239	}
240	if (status != 0) {
241		err_print("Mode sense failed.\n");
242	}
243	return (0);
244}
245
246int
247ca_read_display()
248{
249	struct mode_cache		*page8;
250	struct scsi_ms_header		header;
251	int				status;
252	union {
253		struct mode_cache	page8;
254		char			rawbuf[MAX_MODE_SENSE_SIZE];
255	} u_page8;
256
257	page8 = &u_page8.page8;
258
259	status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
260			MODE_SENSE_PC_CURRENT, (caddr_t)page8,
261			MAX_MODE_SENSE_SIZE, &header);
262
263	if (status == 0) {
264		if (page8->rcd) {
265			fmt_print("Read Cache is disabled\n");
266		} else {
267			fmt_print("Read Cache is enabled\n");
268		}
269	} else {
270		err_print("Mode sense failed.\n");
271	}
272	return (0);
273}
274
275int
276ca_read_enable()
277{
278	struct mode_cache		*page8;
279	struct scsi_ms_header		header;
280	int				status;
281	int				length;
282	int				sp_flags;
283	union {
284		struct mode_cache	page8;
285		char			rawbuf[MAX_MODE_SENSE_SIZE];
286	} u_page8;
287
288	page8 = &u_page8.page8;
289
290	status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
291			MODE_SENSE_PC_CHANGEABLE, (caddr_t)page8,
292			MAX_MODE_SENSE_SIZE, &header);
293
294	if (status == 0) {
295		if (page8->rcd) {
296			status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
297				MODE_SENSE_PC_SAVED, (caddr_t)page8,
298				MAX_MODE_SENSE_SIZE, &header);
299			if (status != 0) {
300				status = uscsi_mode_sense(cur_file,
301				DAD_MODE_CACHE, MODE_SENSE_PC_CURRENT,
302				(caddr_t)page8, MAX_MODE_SENSE_SIZE, &header);
303			}
304
305			if (status == 0) {
306				length = MODESENSE_PAGE_LEN(page8);
307				sp_flags = MODE_SELECT_PF;
308				if (page8->mode_page.ps) {
309					sp_flags |= MODE_SELECT_SP;
310				} else {
311					err_print("\
312This setting is valid until next reset only. It is not saved permanently.\n");
313				}
314				page8->mode_page.ps = 0;
315				page8->rcd = 0;
316				header.mode_header.length = 0;
317				header.mode_header.device_specific = 0;
318				status = uscsi_mode_select(cur_file,
319					DAD_MODE_CACHE, sp_flags,
320					(caddr_t)page8, length, &header);
321				if (status != 0) {
322					err_print("Mode select failed\n");
323					return (0);
324				}
325			}
326		} else {
327			err_print("Read cache setting is not changeable\n");
328		}
329	}
330	if (status != 0) {
331		err_print("Mode sense failed.\n");
332	}
333	return (0);
334}
335
336int
337ca_read_disable()
338{
339	struct mode_cache		*page8;
340	struct scsi_ms_header		header;
341	int				status;
342	int				length;
343	int				sp_flags;
344	union {
345		struct mode_cache	page8;
346		char			rawbuf[MAX_MODE_SENSE_SIZE];
347	} u_page8;
348
349	page8 = &u_page8.page8;
350
351	status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
352		MODE_SENSE_PC_CHANGEABLE, (caddr_t)page8,
353		MAX_MODE_SENSE_SIZE, &header);
354
355	if (status == 0) {
356		if (page8->rcd) {
357			status = uscsi_mode_sense(cur_file, DAD_MODE_CACHE,
358				MODE_SENSE_PC_SAVED, (caddr_t)page8,
359				MAX_MODE_SENSE_SIZE, &header);
360			if (status != 0) {
361				status = uscsi_mode_sense(cur_file,
362				DAD_MODE_CACHE, MODE_SENSE_PC_CURRENT,
363				(caddr_t)page8, MAX_MODE_SENSE_SIZE, &header);
364			}
365
366			if (status == 0) {
367				length = MODESENSE_PAGE_LEN(page8);
368				sp_flags = MODE_SELECT_PF;
369				if (page8->mode_page.ps) {
370					sp_flags |= MODE_SELECT_SP;
371				} else {
372					err_print("\
373This setting is valid until next reset only. It is not saved permanently.\n");
374				}
375				page8->mode_page.ps = 0;
376				page8->rcd = 1;
377				header.mode_header.length = 0;
378				header.mode_header.device_specific = 0;
379				status = uscsi_mode_select(cur_file,
380					DAD_MODE_CACHE, sp_flags,
381					(caddr_t)page8, length, &header);
382				if (status != 0) {
383					err_print("Mode select failed\n");
384					return (0);
385				}
386			}
387		} else {
388			err_print("Read cache setting is not changeable\n");
389		}
390	}
391	if (status != 0) {
392		err_print("Mode sense failed.\n");
393	}
394	return (0);
395}
396