1f6ad3f23SAlexander Motin /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3bec9534dSPedro F. Giffuni *
4f6ad3f23SAlexander Motin * Copyright (c) 2000 Matthew Jacob
5f6ad3f23SAlexander Motin * All rights reserved.
6f6ad3f23SAlexander Motin *
7f6ad3f23SAlexander Motin * Redistribution and use in source and binary forms, with or without
8f6ad3f23SAlexander Motin * modification, are permitted provided that the following conditions
9f6ad3f23SAlexander Motin * are met:
10f6ad3f23SAlexander Motin * 1. Redistributions of source code must retain the above copyright
11f6ad3f23SAlexander Motin * notice, this list of conditions, and the following disclaimer,
12f6ad3f23SAlexander Motin * without modification, immediately at the beginning of the file.
13f6ad3f23SAlexander Motin * 2. The name of the author may not be used to endorse or promote products
14f6ad3f23SAlexander Motin * derived from this software without specific prior written permission.
15f6ad3f23SAlexander Motin *
16f6ad3f23SAlexander Motin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17f6ad3f23SAlexander Motin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18f6ad3f23SAlexander Motin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19f6ad3f23SAlexander Motin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20f6ad3f23SAlexander Motin * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21f6ad3f23SAlexander Motin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22f6ad3f23SAlexander Motin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23f6ad3f23SAlexander Motin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24f6ad3f23SAlexander Motin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25f6ad3f23SAlexander Motin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26f6ad3f23SAlexander Motin * SUCH DAMAGE.
27f6ad3f23SAlexander Motin */
28f6ad3f23SAlexander Motin
29f6ad3f23SAlexander Motin #include <sys/param.h>
30f6ad3f23SAlexander Motin
31f6ad3f23SAlexander Motin #include <sys/conf.h>
32f6ad3f23SAlexander Motin #include <sys/errno.h>
33f6ad3f23SAlexander Motin #include <sys/kernel.h>
34f6ad3f23SAlexander Motin #include <sys/malloc.h>
35f6ad3f23SAlexander Motin #include <sys/mutex.h>
36f6ad3f23SAlexander Motin #include <sys/queue.h>
37f6ad3f23SAlexander Motin #include <sys/sx.h>
38f6ad3f23SAlexander Motin #include <sys/systm.h>
39f6ad3f23SAlexander Motin #include <sys/sysctl.h>
40f6ad3f23SAlexander Motin #include <sys/types.h>
41f6ad3f23SAlexander Motin
42f6ad3f23SAlexander Motin #include <cam/cam.h>
43f6ad3f23SAlexander Motin #include <cam/cam_ccb.h>
44f6ad3f23SAlexander Motin #include <cam/cam_periph.h>
45f6ad3f23SAlexander Motin
46f6ad3f23SAlexander Motin #include <cam/scsi/scsi_enc.h>
47f6ad3f23SAlexander Motin #include <cam/scsi/scsi_enc_internal.h>
48f6ad3f23SAlexander Motin #include <cam/scsi/scsi_message.h>
49f6ad3f23SAlexander Motin
50f6ad3f23SAlexander Motin /*
51f6ad3f23SAlexander Motin * SAF-TE Type Device Emulation
52f6ad3f23SAlexander Motin */
53f6ad3f23SAlexander Motin
54f6ad3f23SAlexander Motin static int safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag);
55f6ad3f23SAlexander Motin
56f6ad3f23SAlexander Motin #define ALL_ENC_STAT (SES_ENCSTAT_CRITICAL | SES_ENCSTAT_UNRECOV | \
57f6ad3f23SAlexander Motin SES_ENCSTAT_NONCRITICAL | SES_ENCSTAT_INFO)
58f6ad3f23SAlexander Motin /*
59f6ad3f23SAlexander Motin * SAF-TE specific defines- Mandatory ones only...
60f6ad3f23SAlexander Motin */
61f6ad3f23SAlexander Motin
62f6ad3f23SAlexander Motin /*
63f6ad3f23SAlexander Motin * READ BUFFER ('get' commands) IDs- placed in offset 2 of cdb
64f6ad3f23SAlexander Motin */
65f6ad3f23SAlexander Motin #define SAFTE_RD_RDCFG 0x00 /* read enclosure configuration */
66f6ad3f23SAlexander Motin #define SAFTE_RD_RDESTS 0x01 /* read enclosure status */
67f6ad3f23SAlexander Motin #define SAFTE_RD_RDDSTS 0x04 /* read drive slot status */
68f6ad3f23SAlexander Motin #define SAFTE_RD_RDGFLG 0x05 /* read global flags */
69f6ad3f23SAlexander Motin
70f6ad3f23SAlexander Motin /*
71f6ad3f23SAlexander Motin * WRITE BUFFER ('set' commands) IDs- placed in offset 0 of databuf
72f6ad3f23SAlexander Motin */
73f6ad3f23SAlexander Motin #define SAFTE_WT_DSTAT 0x10 /* write device slot status */
74f6ad3f23SAlexander Motin #define SAFTE_WT_SLTOP 0x12 /* perform slot operation */
75f6ad3f23SAlexander Motin #define SAFTE_WT_FANSPD 0x13 /* set fan speed */
76f6ad3f23SAlexander Motin #define SAFTE_WT_ACTPWS 0x14 /* turn on/off power supply */
77f6ad3f23SAlexander Motin #define SAFTE_WT_GLOBAL 0x15 /* send global command */
78f6ad3f23SAlexander Motin
79f6ad3f23SAlexander Motin #define SAFT_SCRATCH 64
80f6ad3f23SAlexander Motin #define SCSZ 0x8000
81f6ad3f23SAlexander Motin
82f6ad3f23SAlexander Motin typedef enum {
83f6ad3f23SAlexander Motin SAFTE_UPDATE_NONE,
84f6ad3f23SAlexander Motin SAFTE_UPDATE_READCONFIG,
85f6ad3f23SAlexander Motin SAFTE_UPDATE_READGFLAGS,
86f6ad3f23SAlexander Motin SAFTE_UPDATE_READENCSTATUS,
87f6ad3f23SAlexander Motin SAFTE_UPDATE_READSLOTSTATUS,
88f6ad3f23SAlexander Motin SAFTE_PROCESS_CONTROL_REQS,
89f6ad3f23SAlexander Motin SAFTE_NUM_UPDATE_STATES
90f6ad3f23SAlexander Motin } safte_update_action;
91f6ad3f23SAlexander Motin
92f6ad3f23SAlexander Motin static fsm_fill_handler_t safte_fill_read_buf_io;
93f6ad3f23SAlexander Motin static fsm_fill_handler_t safte_fill_control_request;
94f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_config;
95f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_gflags;
96f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_status;
97f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_slotstatus;
98f6ad3f23SAlexander Motin static fsm_done_handler_t safte_process_control_request;
99f6ad3f23SAlexander Motin
100f6ad3f23SAlexander Motin static struct enc_fsm_state enc_fsm_states[SAFTE_NUM_UPDATE_STATES] =
101f6ad3f23SAlexander Motin {
102f6ad3f23SAlexander Motin { "SAFTE_UPDATE_NONE", 0, 0, 0, NULL, NULL, NULL },
103f6ad3f23SAlexander Motin {
104f6ad3f23SAlexander Motin "SAFTE_UPDATE_READCONFIG",
105f6ad3f23SAlexander Motin SAFTE_RD_RDCFG,
106f6ad3f23SAlexander Motin SAFT_SCRATCH,
107f6ad3f23SAlexander Motin 60 * 1000,
108f6ad3f23SAlexander Motin safte_fill_read_buf_io,
109f6ad3f23SAlexander Motin safte_process_config,
110f6ad3f23SAlexander Motin enc_error
111f6ad3f23SAlexander Motin },
112f6ad3f23SAlexander Motin {
113f6ad3f23SAlexander Motin "SAFTE_UPDATE_READGFLAGS",
114f6ad3f23SAlexander Motin SAFTE_RD_RDGFLG,
115f6ad3f23SAlexander Motin 16,
116f6ad3f23SAlexander Motin 60 * 1000,
117f6ad3f23SAlexander Motin safte_fill_read_buf_io,
118f6ad3f23SAlexander Motin safte_process_gflags,
119f6ad3f23SAlexander Motin enc_error
120f6ad3f23SAlexander Motin },
121f6ad3f23SAlexander Motin {
122f6ad3f23SAlexander Motin "SAFTE_UPDATE_READENCSTATUS",
123f6ad3f23SAlexander Motin SAFTE_RD_RDESTS,
124f6ad3f23SAlexander Motin SCSZ,
125f6ad3f23SAlexander Motin 60 * 1000,
126f6ad3f23SAlexander Motin safte_fill_read_buf_io,
127f6ad3f23SAlexander Motin safte_process_status,
128f6ad3f23SAlexander Motin enc_error
129f6ad3f23SAlexander Motin },
130f6ad3f23SAlexander Motin {
131f6ad3f23SAlexander Motin "SAFTE_UPDATE_READSLOTSTATUS",
132f6ad3f23SAlexander Motin SAFTE_RD_RDDSTS,
133f6ad3f23SAlexander Motin SCSZ,
134f6ad3f23SAlexander Motin 60 * 1000,
135f6ad3f23SAlexander Motin safte_fill_read_buf_io,
136f6ad3f23SAlexander Motin safte_process_slotstatus,
137f6ad3f23SAlexander Motin enc_error
138f6ad3f23SAlexander Motin },
139f6ad3f23SAlexander Motin {
140f6ad3f23SAlexander Motin "SAFTE_PROCESS_CONTROL_REQS",
141f6ad3f23SAlexander Motin 0,
142f6ad3f23SAlexander Motin SCSZ,
143f6ad3f23SAlexander Motin 60 * 1000,
144f6ad3f23SAlexander Motin safte_fill_control_request,
145f6ad3f23SAlexander Motin safte_process_control_request,
146f6ad3f23SAlexander Motin enc_error
147f6ad3f23SAlexander Motin }
148f6ad3f23SAlexander Motin };
149f6ad3f23SAlexander Motin
150f6ad3f23SAlexander Motin typedef struct safte_control_request {
151f6ad3f23SAlexander Motin int elm_idx;
152f6ad3f23SAlexander Motin uint8_t elm_stat[4];
153f6ad3f23SAlexander Motin int result;
154f6ad3f23SAlexander Motin TAILQ_ENTRY(safte_control_request) links;
155f6ad3f23SAlexander Motin } safte_control_request_t;
156f6ad3f23SAlexander Motin TAILQ_HEAD(safte_control_reqlist, safte_control_request);
157f6ad3f23SAlexander Motin typedef struct safte_control_reqlist safte_control_reqlist_t;
158f6ad3f23SAlexander Motin enum {
159f6ad3f23SAlexander Motin SES_SETSTATUS_ENC_IDX = -1
160f6ad3f23SAlexander Motin };
161f6ad3f23SAlexander Motin
162f6ad3f23SAlexander Motin static void
safte_terminate_control_requests(safte_control_reqlist_t * reqlist,int result)163f6ad3f23SAlexander Motin safte_terminate_control_requests(safte_control_reqlist_t *reqlist, int result)
164f6ad3f23SAlexander Motin {
165f6ad3f23SAlexander Motin safte_control_request_t *req;
166f6ad3f23SAlexander Motin
167f6ad3f23SAlexander Motin while ((req = TAILQ_FIRST(reqlist)) != NULL) {
168f6ad3f23SAlexander Motin TAILQ_REMOVE(reqlist, req, links);
169f6ad3f23SAlexander Motin req->result = result;
170f6ad3f23SAlexander Motin wakeup(req);
171f6ad3f23SAlexander Motin }
172f6ad3f23SAlexander Motin }
173f6ad3f23SAlexander Motin
174f6ad3f23SAlexander Motin struct scfg {
175f6ad3f23SAlexander Motin /*
176f6ad3f23SAlexander Motin * Cached Configuration
177f6ad3f23SAlexander Motin */
178f6ad3f23SAlexander Motin uint8_t Nfans; /* Number of Fans */
179f6ad3f23SAlexander Motin uint8_t Npwr; /* Number of Power Supplies */
180f6ad3f23SAlexander Motin uint8_t Nslots; /* Number of Device Slots */
181f6ad3f23SAlexander Motin uint8_t DoorLock; /* Door Lock Installed */
182f6ad3f23SAlexander Motin uint8_t Ntherm; /* Number of Temperature Sensors */
183f6ad3f23SAlexander Motin uint8_t Nspkrs; /* Number of Speakers */
184f6ad3f23SAlexander Motin uint8_t Ntstats; /* Number of Thermostats */
185f6ad3f23SAlexander Motin /*
186f6ad3f23SAlexander Motin * Cached Flag Bytes for Global Status
187f6ad3f23SAlexander Motin */
188f6ad3f23SAlexander Motin uint8_t flag1;
189f6ad3f23SAlexander Motin uint8_t flag2;
190f6ad3f23SAlexander Motin /*
191f6ad3f23SAlexander Motin * What object index ID is where various slots start.
192f6ad3f23SAlexander Motin */
193f6ad3f23SAlexander Motin uint8_t pwroff;
194f6ad3f23SAlexander Motin uint8_t slotoff;
195f6ad3f23SAlexander Motin #define SAFT_ALARM_OFFSET(cc) (cc)->slotoff - 1
196f6ad3f23SAlexander Motin
197f6ad3f23SAlexander Motin encioc_enc_status_t adm_status;
198f6ad3f23SAlexander Motin encioc_enc_status_t enc_status;
199f6ad3f23SAlexander Motin encioc_enc_status_t slot_status;
200f6ad3f23SAlexander Motin
201f6ad3f23SAlexander Motin safte_control_reqlist_t requests;
202f6ad3f23SAlexander Motin safte_control_request_t *current_request;
203f6ad3f23SAlexander Motin int current_request_stage;
204f6ad3f23SAlexander Motin int current_request_stages;
205f6ad3f23SAlexander Motin };
206f6ad3f23SAlexander Motin
207f6ad3f23SAlexander Motin #define SAFT_FLG1_ALARM 0x1
208f6ad3f23SAlexander Motin #define SAFT_FLG1_GLOBFAIL 0x2
209f6ad3f23SAlexander Motin #define SAFT_FLG1_GLOBWARN 0x4
210f6ad3f23SAlexander Motin #define SAFT_FLG1_ENCPWROFF 0x8
211f6ad3f23SAlexander Motin #define SAFT_FLG1_ENCFANFAIL 0x10
212f6ad3f23SAlexander Motin #define SAFT_FLG1_ENCPWRFAIL 0x20
213f6ad3f23SAlexander Motin #define SAFT_FLG1_ENCDRVFAIL 0x40
214f6ad3f23SAlexander Motin #define SAFT_FLG1_ENCDRVWARN 0x80
215f6ad3f23SAlexander Motin
216f6ad3f23SAlexander Motin #define SAFT_FLG2_LOCKDOOR 0x4
217f6ad3f23SAlexander Motin #define SAFT_PRIVATE sizeof (struct scfg)
218f6ad3f23SAlexander Motin
219f6ad3f23SAlexander Motin static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
220f6ad3f23SAlexander Motin #define SAFT_BAIL(r, x) \
221f6ad3f23SAlexander Motin if ((r) >= (x)) { \
2225e6609a2SMatt Jacob ENC_VLOG(enc, safte_2little, x, __LINE__);\
223f6ad3f23SAlexander Motin return (EIO); \
224f6ad3f23SAlexander Motin }
225f6ad3f23SAlexander Motin
226f6ad3f23SAlexander Motin int emulate_array_devices = 1;
227af3b2549SHans Petter Selasky SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RWTUN,
228f6ad3f23SAlexander Motin &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
229f6ad3f23SAlexander Motin
230f6ad3f23SAlexander Motin static int
safte_fill_read_buf_io(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t * buf)231f6ad3f23SAlexander Motin safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state,
232f6ad3f23SAlexander Motin union ccb *ccb, uint8_t *buf)
233f6ad3f23SAlexander Motin {
234f6ad3f23SAlexander Motin
235f6ad3f23SAlexander Motin if (state->page_code != SAFTE_RD_RDCFG &&
236f6ad3f23SAlexander Motin enc->enc_cache.nelms == 0) {
237f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
238f6ad3f23SAlexander Motin return (-1);
239f6ad3f23SAlexander Motin }
240f6ad3f23SAlexander Motin
241f6ad3f23SAlexander Motin if (enc->enc_type == ENC_SEMB_SAFT) {
242f6ad3f23SAlexander Motin semb_read_buffer(&ccb->ataio, /*retries*/5,
243227d67aaSAlexander Motin NULL, MSG_SIMPLE_Q_TAG,
244f6ad3f23SAlexander Motin state->page_code, buf, state->buf_size,
245f6ad3f23SAlexander Motin state->timeout);
246f6ad3f23SAlexander Motin } else {
247f6ad3f23SAlexander Motin scsi_read_buffer(&ccb->csio, /*retries*/5,
248227d67aaSAlexander Motin NULL, MSG_SIMPLE_Q_TAG, 1,
249f6ad3f23SAlexander Motin state->page_code, 0, buf, state->buf_size,
250f6ad3f23SAlexander Motin SSD_FULL_SIZE, state->timeout);
251f6ad3f23SAlexander Motin }
252f6ad3f23SAlexander Motin return (0);
253f6ad3f23SAlexander Motin }
254f6ad3f23SAlexander Motin
255f6ad3f23SAlexander Motin static int
safte_process_config(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)256f6ad3f23SAlexander Motin safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
257f6ad3f23SAlexander Motin union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
258f6ad3f23SAlexander Motin {
259f6ad3f23SAlexander Motin struct scfg *cfg;
260f6ad3f23SAlexander Motin uint8_t *buf = *bufp;
261f6ad3f23SAlexander Motin int i, r;
262f6ad3f23SAlexander Motin
263f6ad3f23SAlexander Motin cfg = enc->enc_private;
264f6ad3f23SAlexander Motin if (cfg == NULL)
265f6ad3f23SAlexander Motin return (ENXIO);
266f6ad3f23SAlexander Motin if (error != 0)
267f6ad3f23SAlexander Motin return (error);
268f6ad3f23SAlexander Motin if (xfer_len < 6) {
2695e6609a2SMatt Jacob ENC_VLOG(enc, "too little data (%d) for configuration\n",
270f6ad3f23SAlexander Motin xfer_len);
271f6ad3f23SAlexander Motin return (EIO);
272f6ad3f23SAlexander Motin }
273f6ad3f23SAlexander Motin cfg->Nfans = buf[0];
274f6ad3f23SAlexander Motin cfg->Npwr = buf[1];
275f6ad3f23SAlexander Motin cfg->Nslots = buf[2];
276f6ad3f23SAlexander Motin cfg->DoorLock = buf[3];
277f6ad3f23SAlexander Motin cfg->Ntherm = buf[4];
278f6ad3f23SAlexander Motin cfg->Nspkrs = buf[5];
279f6ad3f23SAlexander Motin if (xfer_len >= 7)
280f6ad3f23SAlexander Motin cfg->Ntstats = buf[6] & 0x0f;
281f6ad3f23SAlexander Motin else
282f6ad3f23SAlexander Motin cfg->Ntstats = 0;
283f6ad3f23SAlexander Motin ENC_VLOG(enc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d "
284f6ad3f23SAlexander Motin "Ntstats %d\n",
285f6ad3f23SAlexander Motin cfg->Nfans, cfg->Npwr, cfg->Nslots, cfg->DoorLock, cfg->Ntherm,
286f6ad3f23SAlexander Motin cfg->Nspkrs, cfg->Ntstats);
287f6ad3f23SAlexander Motin
288f6ad3f23SAlexander Motin enc->enc_cache.nelms = cfg->Nfans + cfg->Npwr + cfg->Nslots +
289f6ad3f23SAlexander Motin cfg->DoorLock + cfg->Ntherm + cfg->Nspkrs + cfg->Ntstats + 1;
290f6ad3f23SAlexander Motin ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
291f6ad3f23SAlexander Motin enc->enc_cache.elm_map =
292ed246e82SAlexander Motin malloc(enc->enc_cache.nelms * sizeof(enc_element_t),
293ed246e82SAlexander Motin M_SCSIENC, M_WAITOK|M_ZERO);
294f6ad3f23SAlexander Motin
295f6ad3f23SAlexander Motin r = 0;
296f6ad3f23SAlexander Motin /*
297f6ad3f23SAlexander Motin * Note that this is all arranged for the convenience
298f6ad3f23SAlexander Motin * in later fetches of status.
299f6ad3f23SAlexander Motin */
300f6ad3f23SAlexander Motin for (i = 0; i < cfg->Nfans; i++)
30153f5ac13SAlexander Motin enc->enc_cache.elm_map[r++].elm_type = ELMTYP_FAN;
302f6ad3f23SAlexander Motin cfg->pwroff = (uint8_t) r;
303f6ad3f23SAlexander Motin for (i = 0; i < cfg->Npwr; i++)
30453f5ac13SAlexander Motin enc->enc_cache.elm_map[r++].elm_type = ELMTYP_POWER;
305f6ad3f23SAlexander Motin for (i = 0; i < cfg->DoorLock; i++)
30653f5ac13SAlexander Motin enc->enc_cache.elm_map[r++].elm_type = ELMTYP_DOORLOCK;
307f6ad3f23SAlexander Motin if (cfg->Nspkrs > 0)
30853f5ac13SAlexander Motin enc->enc_cache.elm_map[r++].elm_type = ELMTYP_ALARM;
309f6ad3f23SAlexander Motin for (i = 0; i < cfg->Ntherm; i++)
31053f5ac13SAlexander Motin enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
311f6ad3f23SAlexander Motin for (i = 0; i <= cfg->Ntstats; i++)
31253f5ac13SAlexander Motin enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
313f6ad3f23SAlexander Motin cfg->slotoff = (uint8_t) r;
314f6ad3f23SAlexander Motin for (i = 0; i < cfg->Nslots; i++)
31553f5ac13SAlexander Motin enc->enc_cache.elm_map[r++].elm_type =
316f6ad3f23SAlexander Motin emulate_array_devices ? ELMTYP_ARRAY_DEV :
317f6ad3f23SAlexander Motin ELMTYP_DEVICE;
318f6ad3f23SAlexander Motin
319f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_UPDATE_READGFLAGS);
320f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
321f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
322f6ad3f23SAlexander Motin
323f6ad3f23SAlexander Motin return (0);
324f6ad3f23SAlexander Motin }
325f6ad3f23SAlexander Motin
326f6ad3f23SAlexander Motin static int
safte_process_gflags(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)327f6ad3f23SAlexander Motin safte_process_gflags(enc_softc_t *enc, struct enc_fsm_state *state,
328f6ad3f23SAlexander Motin union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
329f6ad3f23SAlexander Motin {
330f6ad3f23SAlexander Motin struct scfg *cfg;
331f6ad3f23SAlexander Motin uint8_t *buf = *bufp;
332f6ad3f23SAlexander Motin
333f6ad3f23SAlexander Motin cfg = enc->enc_private;
334f6ad3f23SAlexander Motin if (cfg == NULL)
335f6ad3f23SAlexander Motin return (ENXIO);
336f6ad3f23SAlexander Motin if (error != 0)
337f6ad3f23SAlexander Motin return (error);
338f6ad3f23SAlexander Motin SAFT_BAIL(3, xfer_len);
339f6ad3f23SAlexander Motin cfg->flag1 = buf[1];
340f6ad3f23SAlexander Motin cfg->flag2 = buf[2];
341f6ad3f23SAlexander Motin
342f6ad3f23SAlexander Motin cfg->adm_status = 0;
343f6ad3f23SAlexander Motin if (cfg->flag1 & SAFT_FLG1_GLOBFAIL)
344f6ad3f23SAlexander Motin cfg->adm_status |= SES_ENCSTAT_CRITICAL;
345f6ad3f23SAlexander Motin else if (cfg->flag1 & SAFT_FLG1_GLOBWARN)
346f6ad3f23SAlexander Motin cfg->adm_status |= SES_ENCSTAT_NONCRITICAL;
347f6ad3f23SAlexander Motin
348f6ad3f23SAlexander Motin return (0);
349f6ad3f23SAlexander Motin }
350f6ad3f23SAlexander Motin
351f6ad3f23SAlexander Motin static int
safte_process_status(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)352f6ad3f23SAlexander Motin safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
353f6ad3f23SAlexander Motin union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
354f6ad3f23SAlexander Motin {
355f6ad3f23SAlexander Motin struct scfg *cfg;
356f6ad3f23SAlexander Motin uint8_t *buf = *bufp;
357f6ad3f23SAlexander Motin int oid, r, i, nitems;
358f6ad3f23SAlexander Motin uint16_t tempflags;
359f6ad3f23SAlexander Motin enc_cache_t *cache = &enc->enc_cache;
360f6ad3f23SAlexander Motin
361f6ad3f23SAlexander Motin cfg = enc->enc_private;
362f6ad3f23SAlexander Motin if (cfg == NULL)
363f6ad3f23SAlexander Motin return (ENXIO);
364f6ad3f23SAlexander Motin if (error != 0)
365f6ad3f23SAlexander Motin return (error);
366f6ad3f23SAlexander Motin
367f6ad3f23SAlexander Motin oid = r = 0;
368f6ad3f23SAlexander Motin cfg->enc_status = 0;
369f6ad3f23SAlexander Motin
370f6ad3f23SAlexander Motin for (nitems = i = 0; i < cfg->Nfans; i++) {
371f6ad3f23SAlexander Motin SAFT_BAIL(r, xfer_len);
372f6ad3f23SAlexander Motin /*
373f6ad3f23SAlexander Motin * 0 = Fan Operational
374f6ad3f23SAlexander Motin * 1 = Fan is malfunctioning
375f6ad3f23SAlexander Motin * 2 = Fan is not present
376f6ad3f23SAlexander Motin * 0x80 = Unknown or Not Reportable Status
377f6ad3f23SAlexander Motin */
378f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] = 0; /* resvd */
379f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[2] = 0; /* resvd */
380f6ad3f23SAlexander Motin if (cfg->flag1 & SAFT_FLG1_ENCFANFAIL)
381f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] |= 0x40;
382f6ad3f23SAlexander Motin else
383f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] &= ~0x40;
384f6ad3f23SAlexander Motin switch ((int)buf[r]) {
385f6ad3f23SAlexander Motin case 0:
386f6ad3f23SAlexander Motin nitems++;
387f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
388f6ad3f23SAlexander Motin if ((cache->elm_map[oid].encstat[3] & 0x37) == 0)
389f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] |= 0x27;
390f6ad3f23SAlexander Motin break;
391f6ad3f23SAlexander Motin
392f6ad3f23SAlexander Motin case 1:
393f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] =
394f6ad3f23SAlexander Motin SES_OBJSTAT_CRIT;
395f6ad3f23SAlexander Motin /*
396f6ad3f23SAlexander Motin * FAIL and FAN STOPPED synthesized
397f6ad3f23SAlexander Motin */
398f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] |= 0x10;
399f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] &= ~0x07;
400f6ad3f23SAlexander Motin /*
401f6ad3f23SAlexander Motin * Enclosure marked with CRITICAL error
402f6ad3f23SAlexander Motin * if only one fan or no thermometers,
403f6ad3f23SAlexander Motin * else the NONCRITICAL error is set.
404f6ad3f23SAlexander Motin */
405f6ad3f23SAlexander Motin if (cfg->Nfans == 1 || (cfg->Ntherm + cfg->Ntstats) == 0)
406f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_CRITICAL;
407f6ad3f23SAlexander Motin else
408f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
409f6ad3f23SAlexander Motin break;
410f6ad3f23SAlexander Motin case 2:
411f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] =
412f6ad3f23SAlexander Motin SES_OBJSTAT_NOTINSTALLED;
413f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] |= 0x10;
414f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] &= ~0x07;
415f6ad3f23SAlexander Motin /*
416f6ad3f23SAlexander Motin * Enclosure marked with CRITICAL error
417f6ad3f23SAlexander Motin * if only one fan or no thermometers,
418f6ad3f23SAlexander Motin * else the NONCRITICAL error is set.
419f6ad3f23SAlexander Motin */
420f6ad3f23SAlexander Motin if (cfg->Nfans == 1)
421f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_CRITICAL;
422f6ad3f23SAlexander Motin else
423f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
424f6ad3f23SAlexander Motin break;
425f6ad3f23SAlexander Motin case 0x80:
426f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
427f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0;
428f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_INFO;
429f6ad3f23SAlexander Motin break;
430f6ad3f23SAlexander Motin default:
431f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
4325e6609a2SMatt Jacob ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i,
433f6ad3f23SAlexander Motin buf[r] & 0xff);
434f6ad3f23SAlexander Motin break;
435f6ad3f23SAlexander Motin }
436f6ad3f23SAlexander Motin cache->elm_map[oid++].svalid = 1;
437f6ad3f23SAlexander Motin r++;
438f6ad3f23SAlexander Motin }
439f6ad3f23SAlexander Motin
440f6ad3f23SAlexander Motin /*
441f6ad3f23SAlexander Motin * No matter how you cut it, no cooling elements when there
442f6ad3f23SAlexander Motin * should be some there is critical.
443f6ad3f23SAlexander Motin */
444f6ad3f23SAlexander Motin if (cfg->Nfans && nitems == 0)
445f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_CRITICAL;
446f6ad3f23SAlexander Motin
447f6ad3f23SAlexander Motin for (i = 0; i < cfg->Npwr; i++) {
448f6ad3f23SAlexander Motin SAFT_BAIL(r, xfer_len);
449f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
450f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] = 0; /* resvd */
451f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[2] = 0; /* resvd */
452f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0x20; /* requested on */
453f6ad3f23SAlexander Motin switch (buf[r]) {
454f6ad3f23SAlexander Motin case 0x00: /* pws operational and on */
455f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
456f6ad3f23SAlexander Motin break;
457f6ad3f23SAlexander Motin case 0x01: /* pws operational and off */
458f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
459f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0x10;
460f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_INFO;
461f6ad3f23SAlexander Motin break;
462f6ad3f23SAlexander Motin case 0x10: /* pws is malfunctioning and commanded on */
463f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
464f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0x61;
465f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
466f6ad3f23SAlexander Motin break;
467f6ad3f23SAlexander Motin
468f6ad3f23SAlexander Motin case 0x11: /* pws is malfunctioning and commanded off */
469f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
470f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0x51;
471f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
472f6ad3f23SAlexander Motin break;
473f6ad3f23SAlexander Motin case 0x20: /* pws is not present */
474f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] =
475f6ad3f23SAlexander Motin SES_OBJSTAT_NOTINSTALLED;
476f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0;
477f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_INFO;
478f6ad3f23SAlexander Motin break;
479f6ad3f23SAlexander Motin case 0x21: /* pws is present */
480f6ad3f23SAlexander Motin /*
481f6ad3f23SAlexander Motin * This is for enclosures that cannot tell whether the
482f6ad3f23SAlexander Motin * device is on or malfunctioning, but know that it is
483f6ad3f23SAlexander Motin * present. Just fall through.
484f6ad3f23SAlexander Motin */
485f6ad3f23SAlexander Motin /* FALLTHROUGH */
486f6ad3f23SAlexander Motin case 0x80: /* Unknown or Not Reportable Status */
487f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
488f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0;
489f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_INFO;
490f6ad3f23SAlexander Motin break;
491f6ad3f23SAlexander Motin default:
4925e6609a2SMatt Jacob ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n",
493f6ad3f23SAlexander Motin i, buf[r] & 0xff);
494f6ad3f23SAlexander Motin break;
495f6ad3f23SAlexander Motin }
496f6ad3f23SAlexander Motin enc->enc_cache.elm_map[oid++].svalid = 1;
497f6ad3f23SAlexander Motin r++;
498f6ad3f23SAlexander Motin }
499f6ad3f23SAlexander Motin
500f6ad3f23SAlexander Motin /*
501f6ad3f23SAlexander Motin * Copy Slot SCSI IDs
502f6ad3f23SAlexander Motin */
503f6ad3f23SAlexander Motin for (i = 0; i < cfg->Nslots; i++) {
504f6ad3f23SAlexander Motin SAFT_BAIL(r, xfer_len);
50553f5ac13SAlexander Motin if (cache->elm_map[cfg->slotoff + i].elm_type == ELMTYP_DEVICE)
506f6ad3f23SAlexander Motin cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
507f6ad3f23SAlexander Motin r++;
508f6ad3f23SAlexander Motin }
509f6ad3f23SAlexander Motin
510f6ad3f23SAlexander Motin /*
511f6ad3f23SAlexander Motin * We always have doorlock status, no matter what,
512f6ad3f23SAlexander Motin * but we only save the status if we have one.
513f6ad3f23SAlexander Motin */
514f6ad3f23SAlexander Motin SAFT_BAIL(r, xfer_len);
515f6ad3f23SAlexander Motin if (cfg->DoorLock) {
516f6ad3f23SAlexander Motin /*
517f6ad3f23SAlexander Motin * 0 = Door Locked
518f6ad3f23SAlexander Motin * 1 = Door Unlocked, or no Lock Installed
519f6ad3f23SAlexander Motin * 0x80 = Unknown or Not Reportable Status
520f6ad3f23SAlexander Motin */
521f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] = 0;
522f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[2] = 0;
523f6ad3f23SAlexander Motin switch (buf[r]) {
524f6ad3f23SAlexander Motin case 0:
525f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
526f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0;
527f6ad3f23SAlexander Motin break;
528f6ad3f23SAlexander Motin case 1:
529f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
530f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 1;
531f6ad3f23SAlexander Motin break;
532f6ad3f23SAlexander Motin case 0x80:
533f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
534f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0;
535f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_INFO;
536f6ad3f23SAlexander Motin break;
537f6ad3f23SAlexander Motin default:
538f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] =
539f6ad3f23SAlexander Motin SES_OBJSTAT_UNSUPPORTED;
5405e6609a2SMatt Jacob ENC_VLOG(enc, "unknown lock status 0x%x\n",
541f6ad3f23SAlexander Motin buf[r] & 0xff);
542f6ad3f23SAlexander Motin break;
543f6ad3f23SAlexander Motin }
544f6ad3f23SAlexander Motin cache->elm_map[oid++].svalid = 1;
545f6ad3f23SAlexander Motin }
546f6ad3f23SAlexander Motin r++;
547f6ad3f23SAlexander Motin
548f6ad3f23SAlexander Motin /*
549f6ad3f23SAlexander Motin * We always have speaker status, no matter what,
550f6ad3f23SAlexander Motin * but we only save the status if we have one.
551f6ad3f23SAlexander Motin */
552f6ad3f23SAlexander Motin SAFT_BAIL(r, xfer_len);
553f6ad3f23SAlexander Motin if (cfg->Nspkrs) {
554f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
555f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] = 0;
556f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[2] = 0;
557f6ad3f23SAlexander Motin if (buf[r] == 0) {
558f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] |= SESCTL_DISABLE;
559f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] |= 0x40;
560f6ad3f23SAlexander Motin }
561f6ad3f23SAlexander Motin cache->elm_map[oid++].svalid = 1;
562f6ad3f23SAlexander Motin }
563f6ad3f23SAlexander Motin r++;
564f6ad3f23SAlexander Motin
565f6ad3f23SAlexander Motin /*
566f6ad3f23SAlexander Motin * Now, for "pseudo" thermometers, we have two bytes
567f6ad3f23SAlexander Motin * of information in enclosure status- 16 bits. Actually,
568f6ad3f23SAlexander Motin * the MSB is a single TEMP ALERT flag indicating whether
569f6ad3f23SAlexander Motin * any other bits are set, but, thanks to fuzzy thinking,
570f6ad3f23SAlexander Motin * in the SAF-TE spec, this can also be set even if no
571f6ad3f23SAlexander Motin * other bits are set, thus making this really another
572f6ad3f23SAlexander Motin * binary temperature sensor.
573f6ad3f23SAlexander Motin */
574f6ad3f23SAlexander Motin
575f6ad3f23SAlexander Motin SAFT_BAIL(r + cfg->Ntherm, xfer_len);
576f6ad3f23SAlexander Motin tempflags = buf[r + cfg->Ntherm];
577f6ad3f23SAlexander Motin SAFT_BAIL(r + cfg->Ntherm + 1, xfer_len);
578f6ad3f23SAlexander Motin tempflags |= (tempflags << 8) | buf[r + cfg->Ntherm + 1];
579f6ad3f23SAlexander Motin
580f6ad3f23SAlexander Motin for (i = 0; i < cfg->Ntherm; i++) {
581f6ad3f23SAlexander Motin SAFT_BAIL(r, xfer_len);
582f6ad3f23SAlexander Motin /*
583f6ad3f23SAlexander Motin * Status is a range from -10 to 245 deg Celsius,
584f6ad3f23SAlexander Motin * which we need to normalize to -20 to -245 according
585f6ad3f23SAlexander Motin * to the latest SCSI spec, which makes little
586f6ad3f23SAlexander Motin * sense since this would overflow an 8bit value.
587f6ad3f23SAlexander Motin * Well, still, the base normalization is -20,
588f6ad3f23SAlexander Motin * not -10, so we have to adjust.
589f6ad3f23SAlexander Motin *
590f6ad3f23SAlexander Motin * So what's over and under temperature?
591f6ad3f23SAlexander Motin * Hmm- we'll state that 'normal' operating
592f6ad3f23SAlexander Motin * is 10 to 40 deg Celsius.
593f6ad3f23SAlexander Motin */
594f6ad3f23SAlexander Motin
595f6ad3f23SAlexander Motin /*
596f6ad3f23SAlexander Motin * Actually.... All of the units that people out in the world
597f6ad3f23SAlexander Motin * seem to have do not come even close to setting a value that
598f6ad3f23SAlexander Motin * complies with this spec.
599f6ad3f23SAlexander Motin *
600f6ad3f23SAlexander Motin * The closest explanation I could find was in an
601f6ad3f23SAlexander Motin * LSI-Logic manual, which seemed to indicate that
602f6ad3f23SAlexander Motin * this value would be set by whatever the I2C code
603f6ad3f23SAlexander Motin * would interpolate from the output of an LM75
604f6ad3f23SAlexander Motin * temperature sensor.
605f6ad3f23SAlexander Motin *
606f6ad3f23SAlexander Motin * This means that it is impossible to use the actual
607f6ad3f23SAlexander Motin * numeric value to predict anything. But we don't want
608f6ad3f23SAlexander Motin * to lose the value. So, we'll propagate the *uncorrected*
609f6ad3f23SAlexander Motin * value and set SES_OBJSTAT_NOTAVAIL. We'll depend on the
610f6ad3f23SAlexander Motin * temperature flags for warnings.
611f6ad3f23SAlexander Motin */
612f6ad3f23SAlexander Motin if (tempflags & (1 << i)) {
613f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
614f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_CRITICAL;
615f6ad3f23SAlexander Motin } else
616f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
617f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] = 0;
618f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[2] = buf[r];
619f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0;
620f6ad3f23SAlexander Motin cache->elm_map[oid++].svalid = 1;
621f6ad3f23SAlexander Motin r++;
622f6ad3f23SAlexander Motin }
623f6ad3f23SAlexander Motin
624f6ad3f23SAlexander Motin for (i = 0; i <= cfg->Ntstats; i++) {
625f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] = 0;
626f6ad3f23SAlexander Motin if (tempflags & (1 <<
627f6ad3f23SAlexander Motin ((i == cfg->Ntstats) ? 15 : (cfg->Ntherm + i)))) {
628f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
629f6ad3f23SAlexander Motin cache->elm_map[4].encstat[2] = 0xff;
630f6ad3f23SAlexander Motin /*
631f6ad3f23SAlexander Motin * Set 'over temperature' failure.
632f6ad3f23SAlexander Motin */
633f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 8;
634f6ad3f23SAlexander Motin cfg->enc_status |= SES_ENCSTAT_CRITICAL;
635f6ad3f23SAlexander Motin } else {
636f6ad3f23SAlexander Motin /*
637f6ad3f23SAlexander Motin * We used to say 'not available' and synthesize a
638f6ad3f23SAlexander Motin * nominal 30 deg (C)- that was wrong. Actually,
639f6ad3f23SAlexander Motin * Just say 'OK', and use the reserved value of
640f6ad3f23SAlexander Motin * zero.
641f6ad3f23SAlexander Motin */
642f6ad3f23SAlexander Motin if ((cfg->Ntherm + cfg->Ntstats) == 0)
643f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] =
644f6ad3f23SAlexander Motin SES_OBJSTAT_NOTAVAIL;
645f6ad3f23SAlexander Motin else
646f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] =
647f6ad3f23SAlexander Motin SES_OBJSTAT_OK;
648f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[2] = 0;
649f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0;
650f6ad3f23SAlexander Motin }
651f6ad3f23SAlexander Motin cache->elm_map[oid++].svalid = 1;
652f6ad3f23SAlexander Motin }
653f6ad3f23SAlexander Motin r += 2;
654f6ad3f23SAlexander Motin
655f6ad3f23SAlexander Motin cache->enc_status =
656f6ad3f23SAlexander Motin cfg->enc_status | cfg->slot_status | cfg->adm_status;
657f6ad3f23SAlexander Motin return (0);
658f6ad3f23SAlexander Motin }
659f6ad3f23SAlexander Motin
660f6ad3f23SAlexander Motin static int
safte_process_slotstatus(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)661f6ad3f23SAlexander Motin safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
662f6ad3f23SAlexander Motin union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
663f6ad3f23SAlexander Motin {
664f6ad3f23SAlexander Motin struct scfg *cfg;
665f6ad3f23SAlexander Motin uint8_t *buf = *bufp;
666f6ad3f23SAlexander Motin enc_cache_t *cache = &enc->enc_cache;
667f6ad3f23SAlexander Motin int oid, r, i;
668f6ad3f23SAlexander Motin
669f6ad3f23SAlexander Motin cfg = enc->enc_private;
670f6ad3f23SAlexander Motin if (cfg == NULL)
671f6ad3f23SAlexander Motin return (ENXIO);
672f6ad3f23SAlexander Motin if (error != 0)
673f6ad3f23SAlexander Motin return (error);
674f6ad3f23SAlexander Motin cfg->slot_status = 0;
675f6ad3f23SAlexander Motin oid = cfg->slotoff;
676f6ad3f23SAlexander Motin for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
677f6ad3f23SAlexander Motin SAFT_BAIL(r+3, xfer_len);
67853f5ac13SAlexander Motin if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV)
679f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] = 0;
680f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
681f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] = 0;
682f6ad3f23SAlexander Motin if ((buf[r+3] & 0x01) == 0) { /* no device */
683f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NOTINSTALLED;
684f6ad3f23SAlexander Motin } else if (buf[r+0] & 0x02) {
685f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
686f6ad3f23SAlexander Motin cfg->slot_status |= SES_ENCSTAT_CRITICAL;
687f6ad3f23SAlexander Motin } else if (buf[r+0] & 0x40) {
688f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
689f6ad3f23SAlexander Motin cfg->slot_status |= SES_ENCSTAT_NONCRITICAL;
690f6ad3f23SAlexander Motin } else {
691f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
692f6ad3f23SAlexander Motin }
693f6ad3f23SAlexander Motin if (buf[r+3] & 0x2) {
694f6ad3f23SAlexander Motin if (buf[r+3] & 0x01)
695f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[2] |= SESCTL_RQSRMV;
696f6ad3f23SAlexander Motin else
697f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[2] |= SESCTL_RQSINS;
698f6ad3f23SAlexander Motin }
699f6ad3f23SAlexander Motin if ((buf[r+3] & 0x04) == 0)
700f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] |= SESCTL_DEVOFF;
701f6ad3f23SAlexander Motin if (buf[r+0] & 0x02)
702f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
703f6ad3f23SAlexander Motin if (buf[r+0] & 0x40)
704f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
70553f5ac13SAlexander Motin if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV) {
706f6ad3f23SAlexander Motin if (buf[r+0] & 0x01)
707f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] |= 0x80;
708f6ad3f23SAlexander Motin if (buf[r+0] & 0x04)
709f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] |= 0x02;
710f6ad3f23SAlexander Motin if (buf[r+0] & 0x08)
711f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] |= 0x04;
712f6ad3f23SAlexander Motin if (buf[r+0] & 0x10)
713f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] |= 0x08;
714f6ad3f23SAlexander Motin if (buf[r+0] & 0x20)
715f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] |= 0x10;
716f6ad3f23SAlexander Motin if (buf[r+1] & 0x01)
717f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] |= 0x20;
718f6ad3f23SAlexander Motin if (buf[r+1] & 0x02)
719f6ad3f23SAlexander Motin cache->elm_map[oid].encstat[1] |= 0x01;
720f6ad3f23SAlexander Motin }
721f6ad3f23SAlexander Motin cache->elm_map[oid++].svalid = 1;
722f6ad3f23SAlexander Motin }
723f6ad3f23SAlexander Motin
724f6ad3f23SAlexander Motin cache->enc_status =
725f6ad3f23SAlexander Motin cfg->enc_status | cfg->slot_status | cfg->adm_status;
726f6ad3f23SAlexander Motin return (0);
727f6ad3f23SAlexander Motin }
728f6ad3f23SAlexander Motin
729f6ad3f23SAlexander Motin static int
safte_fill_control_request(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t * buf)730f6ad3f23SAlexander Motin safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
731f6ad3f23SAlexander Motin union ccb *ccb, uint8_t *buf)
732f6ad3f23SAlexander Motin {
733f6ad3f23SAlexander Motin struct scfg *cfg;
734f6ad3f23SAlexander Motin enc_element_t *ep, *ep1;
735f6ad3f23SAlexander Motin safte_control_request_t *req;
736f6ad3f23SAlexander Motin int i, idx, xfer_len;
737f6ad3f23SAlexander Motin
738f6ad3f23SAlexander Motin cfg = enc->enc_private;
739f6ad3f23SAlexander Motin if (cfg == NULL)
740f6ad3f23SAlexander Motin return (ENXIO);
741f6ad3f23SAlexander Motin
742f6ad3f23SAlexander Motin if (enc->enc_cache.nelms == 0) {
743f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
744f6ad3f23SAlexander Motin return (-1);
745f6ad3f23SAlexander Motin }
746f6ad3f23SAlexander Motin
747f6ad3f23SAlexander Motin if (cfg->current_request == NULL) {
748f6ad3f23SAlexander Motin cfg->current_request = TAILQ_FIRST(&cfg->requests);
749f6ad3f23SAlexander Motin TAILQ_REMOVE(&cfg->requests, cfg->current_request, links);
750f6ad3f23SAlexander Motin cfg->current_request_stage = 0;
751f6ad3f23SAlexander Motin cfg->current_request_stages = 1;
752f6ad3f23SAlexander Motin }
753f6ad3f23SAlexander Motin req = cfg->current_request;
754f6ad3f23SAlexander Motin
755f6ad3f23SAlexander Motin idx = (int)req->elm_idx;
756f6ad3f23SAlexander Motin if (req->elm_idx == SES_SETSTATUS_ENC_IDX) {
757f6ad3f23SAlexander Motin cfg->adm_status = req->elm_stat[0] & ALL_ENC_STAT;
758f6ad3f23SAlexander Motin cfg->flag1 &= ~(SAFT_FLG1_GLOBFAIL|SAFT_FLG1_GLOBWARN);
759f6ad3f23SAlexander Motin if (req->elm_stat[0] & (SES_ENCSTAT_CRITICAL|SES_ENCSTAT_UNRECOV))
760f6ad3f23SAlexander Motin cfg->flag1 |= SAFT_FLG1_GLOBFAIL;
761f6ad3f23SAlexander Motin else if (req->elm_stat[0] & SES_ENCSTAT_NONCRITICAL)
762f6ad3f23SAlexander Motin cfg->flag1 |= SAFT_FLG1_GLOBWARN;
763f6ad3f23SAlexander Motin buf[0] = SAFTE_WT_GLOBAL;
764f6ad3f23SAlexander Motin buf[1] = cfg->flag1;
765f6ad3f23SAlexander Motin buf[2] = cfg->flag2;
766f6ad3f23SAlexander Motin buf[3] = 0;
767f6ad3f23SAlexander Motin xfer_len = 16;
768f6ad3f23SAlexander Motin } else {
769f6ad3f23SAlexander Motin ep = &enc->enc_cache.elm_map[idx];
770f6ad3f23SAlexander Motin
77153f5ac13SAlexander Motin switch (ep->elm_type) {
772f6ad3f23SAlexander Motin case ELMTYP_DEVICE:
773f6ad3f23SAlexander Motin case ELMTYP_ARRAY_DEV:
774f6ad3f23SAlexander Motin switch (cfg->current_request_stage) {
775f6ad3f23SAlexander Motin case 0:
776f6ad3f23SAlexander Motin ep->priv = 0;
777f6ad3f23SAlexander Motin if (req->elm_stat[0] & SESCTL_PRDFAIL)
778f6ad3f23SAlexander Motin ep->priv |= 0x40;
779f6ad3f23SAlexander Motin if (req->elm_stat[3] & SESCTL_RQSFLT)
780f6ad3f23SAlexander Motin ep->priv |= 0x02;
78153f5ac13SAlexander Motin if (ep->elm_type == ELMTYP_ARRAY_DEV) {
782f6ad3f23SAlexander Motin if (req->elm_stat[1] & 0x01)
783f6ad3f23SAlexander Motin ep->priv |= 0x200;
784f6ad3f23SAlexander Motin if (req->elm_stat[1] & 0x02)
785f6ad3f23SAlexander Motin ep->priv |= 0x04;
786f6ad3f23SAlexander Motin if (req->elm_stat[1] & 0x04)
787f6ad3f23SAlexander Motin ep->priv |= 0x08;
788f6ad3f23SAlexander Motin if (req->elm_stat[1] & 0x08)
789f6ad3f23SAlexander Motin ep->priv |= 0x10;
790f6ad3f23SAlexander Motin if (req->elm_stat[1] & 0x10)
791f6ad3f23SAlexander Motin ep->priv |= 0x20;
792f6ad3f23SAlexander Motin if (req->elm_stat[1] & 0x20)
793f6ad3f23SAlexander Motin ep->priv |= 0x100;
794f6ad3f23SAlexander Motin if (req->elm_stat[1] & 0x80)
795f6ad3f23SAlexander Motin ep->priv |= 0x01;
796f6ad3f23SAlexander Motin }
797f6ad3f23SAlexander Motin if (ep->priv == 0)
798f6ad3f23SAlexander Motin ep->priv |= 0x01; /* no errors */
799f6ad3f23SAlexander Motin
800f6ad3f23SAlexander Motin buf[0] = SAFTE_WT_DSTAT;
801f6ad3f23SAlexander Motin for (i = 0; i < cfg->Nslots; i++) {
802f6ad3f23SAlexander Motin ep1 = &enc->enc_cache.elm_map[cfg->slotoff + i];
803f6ad3f23SAlexander Motin buf[1 + (3 * i)] = ep1->priv;
804f6ad3f23SAlexander Motin buf[2 + (3 * i)] = ep1->priv >> 8;
805f6ad3f23SAlexander Motin }
806f6ad3f23SAlexander Motin xfer_len = cfg->Nslots * 3 + 1;
807f6ad3f23SAlexander Motin #define DEVON(x) (!(((x)[2] & SESCTL_RQSINS) | \
808f6ad3f23SAlexander Motin ((x)[2] & SESCTL_RQSRMV) | \
809f6ad3f23SAlexander Motin ((x)[3] & SESCTL_DEVOFF)))
810f6ad3f23SAlexander Motin if (DEVON(req->elm_stat) != DEVON(ep->encstat))
811f6ad3f23SAlexander Motin cfg->current_request_stages++;
812f6ad3f23SAlexander Motin #define IDON(x) (!!((x)[2] & SESCTL_RQSID))
813f6ad3f23SAlexander Motin if (IDON(req->elm_stat) != IDON(ep->encstat))
814f6ad3f23SAlexander Motin cfg->current_request_stages++;
815f6ad3f23SAlexander Motin break;
816f6ad3f23SAlexander Motin case 1:
817f6ad3f23SAlexander Motin case 2:
818f6ad3f23SAlexander Motin buf[0] = SAFTE_WT_SLTOP;
819f6ad3f23SAlexander Motin buf[1] = idx - cfg->slotoff;
820f6ad3f23SAlexander Motin if (cfg->current_request_stage == 1 &&
821f6ad3f23SAlexander Motin DEVON(req->elm_stat) != DEVON(ep->encstat)) {
822f6ad3f23SAlexander Motin if (DEVON(req->elm_stat))
823f6ad3f23SAlexander Motin buf[2] = 0x01;
824f6ad3f23SAlexander Motin else
825f6ad3f23SAlexander Motin buf[2] = 0x02;
826f6ad3f23SAlexander Motin } else {
827f6ad3f23SAlexander Motin if (IDON(req->elm_stat))
828f6ad3f23SAlexander Motin buf[2] = 0x04;
829f6ad3f23SAlexander Motin else
830f6ad3f23SAlexander Motin buf[2] = 0x00;
831f6ad3f23SAlexander Motin ep->encstat[2] &= ~SESCTL_RQSID;
832f6ad3f23SAlexander Motin ep->encstat[2] |= req->elm_stat[2] &
833f6ad3f23SAlexander Motin SESCTL_RQSID;
834f6ad3f23SAlexander Motin }
835f6ad3f23SAlexander Motin xfer_len = 64;
836f6ad3f23SAlexander Motin break;
837f6ad3f23SAlexander Motin default:
838f6ad3f23SAlexander Motin return (EINVAL);
839f6ad3f23SAlexander Motin }
840f6ad3f23SAlexander Motin break;
841f6ad3f23SAlexander Motin case ELMTYP_POWER:
842f6ad3f23SAlexander Motin cfg->current_request_stages = 2;
843f6ad3f23SAlexander Motin switch (cfg->current_request_stage) {
844f6ad3f23SAlexander Motin case 0:
845f6ad3f23SAlexander Motin if (req->elm_stat[3] & SESCTL_RQSTFAIL) {
846f6ad3f23SAlexander Motin cfg->flag1 |= SAFT_FLG1_ENCPWRFAIL;
847f6ad3f23SAlexander Motin } else {
848f6ad3f23SAlexander Motin cfg->flag1 &= ~SAFT_FLG1_ENCPWRFAIL;
849f6ad3f23SAlexander Motin }
850f6ad3f23SAlexander Motin buf[0] = SAFTE_WT_GLOBAL;
851f6ad3f23SAlexander Motin buf[1] = cfg->flag1;
852f6ad3f23SAlexander Motin buf[2] = cfg->flag2;
853f6ad3f23SAlexander Motin buf[3] = 0;
854f6ad3f23SAlexander Motin xfer_len = 16;
855f6ad3f23SAlexander Motin break;
856f6ad3f23SAlexander Motin case 1:
857f6ad3f23SAlexander Motin buf[0] = SAFTE_WT_ACTPWS;
858f6ad3f23SAlexander Motin buf[1] = idx - cfg->pwroff;
859f6ad3f23SAlexander Motin if (req->elm_stat[3] & SESCTL_RQSTON)
860f6ad3f23SAlexander Motin buf[2] = 0x01;
861f6ad3f23SAlexander Motin else
862f6ad3f23SAlexander Motin buf[2] = 0x00;
863f6ad3f23SAlexander Motin buf[3] = 0;
864f6ad3f23SAlexander Motin xfer_len = 16;
865f6ad3f23SAlexander Motin default:
866f6ad3f23SAlexander Motin return (EINVAL);
867f6ad3f23SAlexander Motin }
868f6ad3f23SAlexander Motin break;
869f6ad3f23SAlexander Motin case ELMTYP_FAN:
870f6ad3f23SAlexander Motin if ((req->elm_stat[3] & 0x7) != 0)
871f6ad3f23SAlexander Motin cfg->current_request_stages = 2;
872f6ad3f23SAlexander Motin switch (cfg->current_request_stage) {
873f6ad3f23SAlexander Motin case 0:
874f6ad3f23SAlexander Motin if (req->elm_stat[3] & SESCTL_RQSTFAIL)
875f6ad3f23SAlexander Motin cfg->flag1 |= SAFT_FLG1_ENCFANFAIL;
876f6ad3f23SAlexander Motin else
877f6ad3f23SAlexander Motin cfg->flag1 &= ~SAFT_FLG1_ENCFANFAIL;
878f6ad3f23SAlexander Motin buf[0] = SAFTE_WT_GLOBAL;
879f6ad3f23SAlexander Motin buf[1] = cfg->flag1;
880f6ad3f23SAlexander Motin buf[2] = cfg->flag2;
881f6ad3f23SAlexander Motin buf[3] = 0;
882f6ad3f23SAlexander Motin xfer_len = 16;
883f6ad3f23SAlexander Motin break;
884f6ad3f23SAlexander Motin case 1:
885f6ad3f23SAlexander Motin buf[0] = SAFTE_WT_FANSPD;
886f6ad3f23SAlexander Motin buf[1] = idx;
887f6ad3f23SAlexander Motin if (req->elm_stat[3] & SESCTL_RQSTON) {
888f6ad3f23SAlexander Motin if ((req->elm_stat[3] & 0x7) == 7)
889f6ad3f23SAlexander Motin buf[2] = 4;
890f6ad3f23SAlexander Motin else if ((req->elm_stat[3] & 0x7) >= 5)
891f6ad3f23SAlexander Motin buf[2] = 3;
892f6ad3f23SAlexander Motin else if ((req->elm_stat[3] & 0x7) >= 3)
893f6ad3f23SAlexander Motin buf[2] = 2;
894f6ad3f23SAlexander Motin else
895f6ad3f23SAlexander Motin buf[2] = 1;
896f6ad3f23SAlexander Motin } else
897f6ad3f23SAlexander Motin buf[2] = 0;
898f6ad3f23SAlexander Motin buf[3] = 0;
899f6ad3f23SAlexander Motin xfer_len = 16;
900f6ad3f23SAlexander Motin ep->encstat[3] = req->elm_stat[3] & 0x67;
901f6ad3f23SAlexander Motin default:
902f6ad3f23SAlexander Motin return (EINVAL);
903f6ad3f23SAlexander Motin }
904f6ad3f23SAlexander Motin break;
905f6ad3f23SAlexander Motin case ELMTYP_DOORLOCK:
906f6ad3f23SAlexander Motin if (req->elm_stat[3] & 0x1)
907f6ad3f23SAlexander Motin cfg->flag2 &= ~SAFT_FLG2_LOCKDOOR;
908f6ad3f23SAlexander Motin else
909f6ad3f23SAlexander Motin cfg->flag2 |= SAFT_FLG2_LOCKDOOR;
910f6ad3f23SAlexander Motin buf[0] = SAFTE_WT_GLOBAL;
911f6ad3f23SAlexander Motin buf[1] = cfg->flag1;
912f6ad3f23SAlexander Motin buf[2] = cfg->flag2;
913f6ad3f23SAlexander Motin buf[3] = 0;
914f6ad3f23SAlexander Motin xfer_len = 16;
915f6ad3f23SAlexander Motin break;
916f6ad3f23SAlexander Motin case ELMTYP_ALARM:
917f6ad3f23SAlexander Motin if ((req->elm_stat[0] & SESCTL_DISABLE) ||
918f6ad3f23SAlexander Motin (req->elm_stat[3] & 0x40)) {
919f6ad3f23SAlexander Motin cfg->flag2 &= ~SAFT_FLG1_ALARM;
920f6ad3f23SAlexander Motin } else if ((req->elm_stat[3] & 0x0f) != 0) {
921f6ad3f23SAlexander Motin cfg->flag2 |= SAFT_FLG1_ALARM;
922f6ad3f23SAlexander Motin } else {
923f6ad3f23SAlexander Motin cfg->flag2 &= ~SAFT_FLG1_ALARM;
924f6ad3f23SAlexander Motin }
925f6ad3f23SAlexander Motin buf[0] = SAFTE_WT_GLOBAL;
926f6ad3f23SAlexander Motin buf[1] = cfg->flag1;
927f6ad3f23SAlexander Motin buf[2] = cfg->flag2;
928f6ad3f23SAlexander Motin buf[3] = 0;
929f6ad3f23SAlexander Motin xfer_len = 16;
930f6ad3f23SAlexander Motin ep->encstat[3] = req->elm_stat[3];
931f6ad3f23SAlexander Motin break;
932f6ad3f23SAlexander Motin default:
933f6ad3f23SAlexander Motin return (EINVAL);
934f6ad3f23SAlexander Motin }
935f6ad3f23SAlexander Motin }
936f6ad3f23SAlexander Motin
937f6ad3f23SAlexander Motin if (enc->enc_type == ENC_SEMB_SAFT) {
938f6ad3f23SAlexander Motin semb_write_buffer(&ccb->ataio, /*retries*/5,
939227d67aaSAlexander Motin NULL, MSG_SIMPLE_Q_TAG,
940f6ad3f23SAlexander Motin buf, xfer_len, state->timeout);
941f6ad3f23SAlexander Motin } else {
942f6ad3f23SAlexander Motin scsi_write_buffer(&ccb->csio, /*retries*/5,
943227d67aaSAlexander Motin NULL, MSG_SIMPLE_Q_TAG, 1,
944f6ad3f23SAlexander Motin 0, 0, buf, xfer_len,
945f6ad3f23SAlexander Motin SSD_FULL_SIZE, state->timeout);
946f6ad3f23SAlexander Motin }
947f6ad3f23SAlexander Motin return (0);
948f6ad3f23SAlexander Motin }
949f6ad3f23SAlexander Motin
950f6ad3f23SAlexander Motin static int
safte_process_control_request(enc_softc_t * enc,struct enc_fsm_state * state,union ccb * ccb,uint8_t ** bufp,int error,int xfer_len)951f6ad3f23SAlexander Motin safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
952f6ad3f23SAlexander Motin union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
953f6ad3f23SAlexander Motin {
954f6ad3f23SAlexander Motin struct scfg *cfg;
955f6ad3f23SAlexander Motin safte_control_request_t *req;
956f6ad3f23SAlexander Motin int idx, type;
957f6ad3f23SAlexander Motin
958f6ad3f23SAlexander Motin cfg = enc->enc_private;
959f6ad3f23SAlexander Motin if (cfg == NULL)
960f6ad3f23SAlexander Motin return (ENXIO);
961f6ad3f23SAlexander Motin
962f6ad3f23SAlexander Motin req = cfg->current_request;
963f6ad3f23SAlexander Motin if (req->result == 0)
964f6ad3f23SAlexander Motin req->result = error;
965f6ad3f23SAlexander Motin if (++cfg->current_request_stage >= cfg->current_request_stages) {
966f6ad3f23SAlexander Motin idx = req->elm_idx;
967f6ad3f23SAlexander Motin if (idx == SES_SETSTATUS_ENC_IDX)
968f6ad3f23SAlexander Motin type = -1;
969f6ad3f23SAlexander Motin else
97053f5ac13SAlexander Motin type = enc->enc_cache.elm_map[idx].elm_type;
971f6ad3f23SAlexander Motin if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
972f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
973f6ad3f23SAlexander Motin else
974f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
975f6ad3f23SAlexander Motin cfg->current_request = NULL;
976f6ad3f23SAlexander Motin wakeup(req);
977f6ad3f23SAlexander Motin } else {
978f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
979f6ad3f23SAlexander Motin }
980f6ad3f23SAlexander Motin return (0);
981f6ad3f23SAlexander Motin }
982f6ad3f23SAlexander Motin
983f6ad3f23SAlexander Motin static void
safte_softc_invalidate(enc_softc_t * enc)984f6ad3f23SAlexander Motin safte_softc_invalidate(enc_softc_t *enc)
985f6ad3f23SAlexander Motin {
986f6ad3f23SAlexander Motin struct scfg *cfg;
987f6ad3f23SAlexander Motin
988f6ad3f23SAlexander Motin cfg = enc->enc_private;
989f6ad3f23SAlexander Motin safte_terminate_control_requests(&cfg->requests, ENXIO);
990f6ad3f23SAlexander Motin }
991f6ad3f23SAlexander Motin
992f6ad3f23SAlexander Motin static void
safte_softc_cleanup(enc_softc_t * enc)993f6ad3f23SAlexander Motin safte_softc_cleanup(enc_softc_t *enc)
994f6ad3f23SAlexander Motin {
995f6ad3f23SAlexander Motin
996f6ad3f23SAlexander Motin ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
997f6ad3f23SAlexander Motin ENC_FREE_AND_NULL(enc->enc_private);
998f6ad3f23SAlexander Motin enc->enc_cache.nelms = 0;
999f6ad3f23SAlexander Motin }
1000f6ad3f23SAlexander Motin
1001f6ad3f23SAlexander Motin static int
safte_init_enc(enc_softc_t * enc)1002f6ad3f23SAlexander Motin safte_init_enc(enc_softc_t *enc)
1003f6ad3f23SAlexander Motin {
1004f6ad3f23SAlexander Motin struct scfg *cfg;
1005f6ad3f23SAlexander Motin int err;
1006f6ad3f23SAlexander Motin static char cdb0[6] = { SEND_DIAGNOSTIC };
1007f6ad3f23SAlexander Motin
1008f6ad3f23SAlexander Motin cfg = enc->enc_private;
1009f6ad3f23SAlexander Motin if (cfg == NULL)
1010f6ad3f23SAlexander Motin return (ENXIO);
1011f6ad3f23SAlexander Motin
1012f6ad3f23SAlexander Motin err = enc_runcmd(enc, cdb0, 6, NULL, 0);
1013f6ad3f23SAlexander Motin if (err) {
1014f6ad3f23SAlexander Motin return (err);
1015f6ad3f23SAlexander Motin }
1016f6ad3f23SAlexander Motin DELAY(5000);
1017f6ad3f23SAlexander Motin cfg->flag1 = 0;
1018f6ad3f23SAlexander Motin cfg->flag2 = 0;
1019f6ad3f23SAlexander Motin err = safte_set_enc_status(enc, 0, 1);
1020f6ad3f23SAlexander Motin return (err);
1021f6ad3f23SAlexander Motin }
1022f6ad3f23SAlexander Motin
1023f6ad3f23SAlexander Motin static int
safte_set_enc_status(enc_softc_t * enc,uint8_t encstat,int slpflag)1024f6ad3f23SAlexander Motin safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
1025f6ad3f23SAlexander Motin {
1026f6ad3f23SAlexander Motin struct scfg *cfg;
1027f6ad3f23SAlexander Motin safte_control_request_t req;
1028f6ad3f23SAlexander Motin
1029f6ad3f23SAlexander Motin cfg = enc->enc_private;
1030f6ad3f23SAlexander Motin if (cfg == NULL)
1031f6ad3f23SAlexander Motin return (ENXIO);
1032f6ad3f23SAlexander Motin
1033f6ad3f23SAlexander Motin req.elm_idx = SES_SETSTATUS_ENC_IDX;
1034f6ad3f23SAlexander Motin req.elm_stat[0] = encstat & 0xf;
1035f6ad3f23SAlexander Motin req.result = 0;
1036f6ad3f23SAlexander Motin
1037f6ad3f23SAlexander Motin TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1038f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1039f6ad3f23SAlexander Motin cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1040f6ad3f23SAlexander Motin
1041f6ad3f23SAlexander Motin return (req.result);
1042f6ad3f23SAlexander Motin }
1043f6ad3f23SAlexander Motin
1044f6ad3f23SAlexander Motin static int
safte_get_elm_status(enc_softc_t * enc,encioc_elm_status_t * elms,int slpflg)1045f6ad3f23SAlexander Motin safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg)
1046f6ad3f23SAlexander Motin {
1047f6ad3f23SAlexander Motin int i = (int)elms->elm_idx;
1048f6ad3f23SAlexander Motin
1049f6ad3f23SAlexander Motin elms->cstat[0] = enc->enc_cache.elm_map[i].encstat[0];
1050f6ad3f23SAlexander Motin elms->cstat[1] = enc->enc_cache.elm_map[i].encstat[1];
1051f6ad3f23SAlexander Motin elms->cstat[2] = enc->enc_cache.elm_map[i].encstat[2];
1052f6ad3f23SAlexander Motin elms->cstat[3] = enc->enc_cache.elm_map[i].encstat[3];
1053f6ad3f23SAlexander Motin return (0);
1054f6ad3f23SAlexander Motin }
1055f6ad3f23SAlexander Motin
1056f6ad3f23SAlexander Motin static int
safte_set_elm_status(enc_softc_t * enc,encioc_elm_status_t * elms,int slpflag)1057f6ad3f23SAlexander Motin safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
1058f6ad3f23SAlexander Motin {
1059f6ad3f23SAlexander Motin struct scfg *cfg;
1060f6ad3f23SAlexander Motin safte_control_request_t req;
1061f6ad3f23SAlexander Motin
1062f6ad3f23SAlexander Motin cfg = enc->enc_private;
1063f6ad3f23SAlexander Motin if (cfg == NULL)
1064f6ad3f23SAlexander Motin return (ENXIO);
1065f6ad3f23SAlexander Motin
1066f6ad3f23SAlexander Motin /* If this is clear, we don't do diddly. */
1067f6ad3f23SAlexander Motin if ((elms->cstat[0] & SESCTL_CSEL) == 0)
1068f6ad3f23SAlexander Motin return (0);
1069f6ad3f23SAlexander Motin
1070f6ad3f23SAlexander Motin req.elm_idx = elms->elm_idx;
1071f6ad3f23SAlexander Motin memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
1072f6ad3f23SAlexander Motin req.result = 0;
1073f6ad3f23SAlexander Motin
1074f6ad3f23SAlexander Motin TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
1075f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
1076f6ad3f23SAlexander Motin cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
1077f6ad3f23SAlexander Motin
1078f6ad3f23SAlexander Motin return (req.result);
1079f6ad3f23SAlexander Motin }
1080f6ad3f23SAlexander Motin
1081f6ad3f23SAlexander Motin static void
safte_poll_status(enc_softc_t * enc)1082f6ad3f23SAlexander Motin safte_poll_status(enc_softc_t *enc)
1083f6ad3f23SAlexander Motin {
1084f6ad3f23SAlexander Motin
1085f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
1086f6ad3f23SAlexander Motin enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
1087f6ad3f23SAlexander Motin }
1088f6ad3f23SAlexander Motin
1089f6ad3f23SAlexander Motin static struct enc_vec safte_enc_vec =
1090f6ad3f23SAlexander Motin {
1091f6ad3f23SAlexander Motin .softc_invalidate = safte_softc_invalidate,
1092f6ad3f23SAlexander Motin .softc_cleanup = safte_softc_cleanup,
1093f6ad3f23SAlexander Motin .init_enc = safte_init_enc,
1094f6ad3f23SAlexander Motin .set_enc_status = safte_set_enc_status,
1095f6ad3f23SAlexander Motin .get_elm_status = safte_get_elm_status,
1096f6ad3f23SAlexander Motin .set_elm_status = safte_set_elm_status,
1097f6ad3f23SAlexander Motin .poll_status = safte_poll_status
1098f6ad3f23SAlexander Motin };
1099f6ad3f23SAlexander Motin
1100f6ad3f23SAlexander Motin int
safte_softc_init(enc_softc_t * enc)1101f6ad3f23SAlexander Motin safte_softc_init(enc_softc_t *enc)
1102f6ad3f23SAlexander Motin {
1103f6ad3f23SAlexander Motin struct scfg *cfg;
1104f6ad3f23SAlexander Motin
1105f6ad3f23SAlexander Motin enc->enc_vec = safte_enc_vec;
1106f6ad3f23SAlexander Motin enc->enc_fsm_states = enc_fsm_states;
1107f6ad3f23SAlexander Motin
1108f6ad3f23SAlexander Motin if (enc->enc_private == NULL) {
1109f6ad3f23SAlexander Motin enc->enc_private = ENC_MALLOCZ(SAFT_PRIVATE);
1110f6ad3f23SAlexander Motin if (enc->enc_private == NULL)
1111f6ad3f23SAlexander Motin return (ENOMEM);
1112f6ad3f23SAlexander Motin }
1113f6ad3f23SAlexander Motin cfg = enc->enc_private;
1114f6ad3f23SAlexander Motin
1115f6ad3f23SAlexander Motin enc->enc_cache.nelms = 0;
1116f6ad3f23SAlexander Motin enc->enc_cache.enc_status = 0;
1117f6ad3f23SAlexander Motin
1118f6ad3f23SAlexander Motin TAILQ_INIT(&cfg->requests);
1119f6ad3f23SAlexander Motin return (0);
1120f6ad3f23SAlexander Motin }
1121