1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte * CDDL HEADER START
3fcf3ce44SJohn Forte *
4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte *
8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte * and limitations under the License.
12fcf3ce44SJohn Forte *
13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte *
19fcf3ce44SJohn Forte * CDDL HEADER END
20fcf3ce44SJohn Forte */
21fcf3ce44SJohn Forte /*
22fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23fcf3ce44SJohn Forte * Use is subject to license terms.
24fcf3ce44SJohn Forte */
25fcf3ce44SJohn Forte
26fcf3ce44SJohn Forte
27fcf3ce44SJohn Forte /*
28fcf3ce44SJohn Forte * I18N message number ranges
29fcf3ce44SJohn Forte * This file: 4500 - 4999
30fcf3ce44SJohn Forte * Shared common messages: 1 - 1999
31fcf3ce44SJohn Forte */
32fcf3ce44SJohn Forte
33fcf3ce44SJohn Forte #include <fcntl.h>
34fcf3ce44SJohn Forte #include <limits.h>
35fcf3ce44SJohn Forte #include <setjmp.h>
36fcf3ce44SJohn Forte #include <signal.h>
37fcf3ce44SJohn Forte #include <siginfo.h>
38fcf3ce44SJohn Forte #include <stdio.h>
39fcf3ce44SJohn Forte #include <stdlib.h>
40fcf3ce44SJohn Forte #include <string.h>
41fcf3ce44SJohn Forte #include <strings.h>
42fcf3ce44SJohn Forte #include <unistd.h>
43fcf3ce44SJohn Forte #include <ctype.h>
44fcf3ce44SJohn Forte #include <dirent.h>
45fcf3ce44SJohn Forte #include <sys/exec.h>
46fcf3ce44SJohn Forte #include <sys/exechdr.h>
47fcf3ce44SJohn Forte #include <sys/mman.h>
48fcf3ce44SJohn Forte #include <sys/stat.h>
49fcf3ce44SJohn Forte #include <sys/types.h>
50fcf3ce44SJohn Forte #include <sys/fibre-channel/fcio.h>
51fcf3ce44SJohn Forte #include <sys/socalreg.h>
52fcf3ce44SJohn Forte /*
53fcf3ce44SJohn Forte * The following define is not to
54fcf3ce44SJohn Forte * include sys/fc4/fcal_linkapp.h
55fcf3ce44SJohn Forte * file from sys/socalio.h, since it
56fcf3ce44SJohn Forte * has same structure defines as in
57fcf3ce44SJohn Forte * sys/fibre-channel/fcio.h.
58fcf3ce44SJohn Forte */
59fcf3ce44SJohn Forte #define _SYS_FC4_FCAL_LINKAPP_H
60fcf3ce44SJohn Forte #include <sys/socalio.h>
61fcf3ce44SJohn Forte #include <sys/time.h>
62fcf3ce44SJohn Forte #include <nl_types.h>
63fcf3ce44SJohn Forte #include <errno.h>
64fcf3ce44SJohn Forte #include <stgcom.h>
65fcf3ce44SJohn Forte #include <gfc.h>
66fcf3ce44SJohn Forte #include <l_common.h>
67fcf3ce44SJohn Forte #include "luxadm.h"
68fcf3ce44SJohn Forte
69525fef19SToomas Soome /* Defines */
70fcf3ce44SJohn Forte #define FEPROM_SIZE 256*1024
71fcf3ce44SJohn Forte #define FEPROM_MAX_PROGRAM 25
72fcf3ce44SJohn Forte #define FEPROM_MAX_ERASE 1000
73fcf3ce44SJohn Forte #define FEPROM_READ_MEMORY 0x00
74fcf3ce44SJohn Forte #define FEPROM_ERASE 0x20
75fcf3ce44SJohn Forte #define FEPROM_ERASE_VERIFY 0xa0
76fcf3ce44SJohn Forte #define FEPROM_PROGRAM 0x40
77fcf3ce44SJohn Forte #define FEPROM_PROGRAM_VERIFY 0xc0
78fcf3ce44SJohn Forte #define FEPROM_RESET 0xff
79fcf3ce44SJohn Forte #define HBA_MAX 128
80fcf3ce44SJohn Forte
81fcf3ce44SJohn Forte #define FOUND 0
82fcf3ce44SJohn Forte #define NOT_FOUND 1
83fcf3ce44SJohn Forte #define PROM_SIZ 0x20010
84fcf3ce44SJohn Forte
85fcf3ce44SJohn Forte #define MAX_RETRIES 3
86fcf3ce44SJohn Forte #define MAX_WAIT_TIME 30
87fcf3ce44SJohn Forte
88fcf3ce44SJohn Forte /*
89fcf3ce44SJohn Forte * The next define is to work around a problem with sbusmem driver not
90fcf3ce44SJohn Forte * able to round up mmap() requests that are not around page boundaries.
91fcf3ce44SJohn Forte */
92fcf3ce44SJohn Forte #define PROM_SIZ_ROUNDED 0x22000
93fcf3ce44SJohn Forte #define SAMPLE_SIZ 0x100
94fcf3ce44SJohn Forte
95fcf3ce44SJohn Forte #define REG_OFFSET 0x20000
96fcf3ce44SJohn Forte
97fcf3ce44SJohn Forte #define FEPROM_WWN_OFFSET 0x3fe00
98fcf3ce44SJohn Forte
99fcf3ce44SJohn Forte #define FEPROM_SUN_WWN 0x50200200
100fcf3ce44SJohn Forte
101fcf3ce44SJohn Forte /*
102fcf3ce44SJohn Forte * We'll leave this on leadville, as the onboard
103fcf3ce44SJohn Forte * isn't allowed to be zapped by luxadm
104fcf3ce44SJohn Forte */
105fcf3ce44SJohn Forte
106fcf3ce44SJohn Forte #define ONBOARD_SOCAL "SUNW,socal@d"
107fcf3ce44SJohn Forte
108fcf3ce44SJohn Forte #define SOCAL_STR "SUNW,socal"
109fcf3ce44SJohn Forte #define SOCAL_STR_LEN 10
110fcf3ce44SJohn Forte
111fcf3ce44SJohn Forte
112fcf3ce44SJohn Forte static uchar_t buffer[FEPROM_SIZE];
113fcf3ce44SJohn Forte
114fcf3ce44SJohn Forte static char sbus_list[HBA_MAX][PATH_MAX];
115fcf3ce44SJohn Forte static char sbussoc_list[HBA_MAX][PATH_MAX];
116fcf3ce44SJohn Forte static char bootpath[PATH_MAX];
117fcf3ce44SJohn Forte static char version[MAXNAMELEN];
118fcf3ce44SJohn Forte
119fcf3ce44SJohn Forte static uint_t getsbuslist(void);
120fcf3ce44SJohn Forte static int load_file(char *, caddr_t, volatile socal_reg_t *);
121fcf3ce44SJohn Forte static void usec_delay(int);
122fcf3ce44SJohn Forte static void getbootdev(unsigned int);
123fcf3ce44SJohn Forte static void getsocpath(char *, int *);
124fcf3ce44SJohn Forte static int loadsocpath(const char *, int *);
125fcf3ce44SJohn Forte static int warn(void);
126fcf3ce44SJohn Forte static int findversion(int, uchar_t *);
127fcf3ce44SJohn Forte static int write_feprom(uchar_t *, uchar_t *, volatile socal_reg_t *);
128fcf3ce44SJohn Forte static int feprom_erase(volatile uchar_t *, volatile socal_reg_t *);
129fcf3ce44SJohn Forte
130fcf3ce44SJohn Forte static struct exec exec;
131fcf3ce44SJohn Forte
132fcf3ce44SJohn Forte int
fcal_update(unsigned int verbose,char * file)133fcf3ce44SJohn Forte fcal_update(unsigned int verbose, char *file)
134fcf3ce44SJohn Forte /*ARGSUSED*/
135fcf3ce44SJohn Forte {
136fcf3ce44SJohn Forte int fd, strfound = 0, retval = 0;
137fcf3ce44SJohn Forte int fbuf_idx, fd1, bytes_read;
138fcf3ce44SJohn Forte caddr_t addr;
139fcf3ce44SJohn Forte uint_t i;
140fcf3ce44SJohn Forte uint_t fflag = 0;
141fcf3ce44SJohn Forte uint_t vflag = 0;
142fcf3ce44SJohn Forte uint_t numslots;
143fcf3ce44SJohn Forte volatile socal_reg_t *regs;
144fcf3ce44SJohn Forte char *slotname, socal[MAXNAMELEN];
145fcf3ce44SJohn Forte char fbuf[BUFSIZ];
146fcf3ce44SJohn Forte
147fcf3ce44SJohn Forte if (!file)
148fcf3ce44SJohn Forte vflag++;
149fcf3ce44SJohn Forte else {
150fcf3ce44SJohn Forte fflag++;
151fcf3ce44SJohn Forte if ((fd1 = open(file, O_RDONLY)) == -1) {
152fcf3ce44SJohn Forte (void) fprintf(stderr,
153fcf3ce44SJohn Forte MSGSTR(4500,
154fcf3ce44SJohn Forte "Error: open() failed on file "
155fcf3ce44SJohn Forte "%s\n"), file);
156fcf3ce44SJohn Forte return (1);
157fcf3ce44SJohn Forte }
158fcf3ce44SJohn Forte /*
159fcf3ce44SJohn Forte * We will just make a check to see if it the file
160fcf3ce44SJohn Forte * has the "SUNW,socal" strings in it
161fcf3ce44SJohn Forte * We cannot use strstr() here because we are operating on
162fcf3ce44SJohn Forte * binary data and so is very likely to have embedded NULLs
163fcf3ce44SJohn Forte */
164fcf3ce44SJohn Forte while (!strfound && ((bytes_read = read(fd1,
165fcf3ce44SJohn Forte fbuf, BUFSIZ)) > 0)) {
166fcf3ce44SJohn Forte for (fbuf_idx = 0; fbuf_idx < bytes_read;
167fcf3ce44SJohn Forte fbuf_idx++) {
168fcf3ce44SJohn Forte /* First check for the SUNW,socal string */
169fcf3ce44SJohn Forte if (strncmp((fbuf + fbuf_idx), SOCAL_STR,
170fcf3ce44SJohn Forte SOCAL_STR_LEN) == 0) {
171fcf3ce44SJohn Forte strfound = 1;
172fcf3ce44SJohn Forte break;
173fcf3ce44SJohn Forte }
174fcf3ce44SJohn Forte
175fcf3ce44SJohn Forte }
176fcf3ce44SJohn Forte }
177fcf3ce44SJohn Forte (void) close(fd1);
178fcf3ce44SJohn Forte
179fcf3ce44SJohn Forte if (!strfound) {
180fcf3ce44SJohn Forte (void) fprintf(stderr,
181fcf3ce44SJohn Forte MSGSTR(4501,
182fcf3ce44SJohn Forte "Error: %s is not a "
183fcf3ce44SJohn Forte "FC100/S Fcode file\n"), file);
184fcf3ce44SJohn Forte return (1);
185fcf3ce44SJohn Forte }
186fcf3ce44SJohn Forte }
187fcf3ce44SJohn Forte
188fcf3ce44SJohn Forte /*
189fcf3ce44SJohn Forte * Get count of, and names of SBus slots using the SBus memory
190fcf3ce44SJohn Forte * interface.
191fcf3ce44SJohn Forte */
192fcf3ce44SJohn Forte (void) getbootdev(verbose);
193fcf3ce44SJohn Forte if (getenv("_LUX_D_DEBUG") != NULL) {
194fcf3ce44SJohn Forte (void) fprintf(stdout, " Bootpath: %s\n", bootpath);
195fcf3ce44SJohn Forte }
196fcf3ce44SJohn Forte
197fcf3ce44SJohn Forte numslots = getsbuslist();
198fcf3ce44SJohn Forte (void) fprintf(stdout,
199fcf3ce44SJohn Forte MSGSTR(4503, "\n Found Path to %d FC100/S Cards\n"), numslots);
200fcf3ce44SJohn Forte
201fcf3ce44SJohn Forte for (i = 0; i < numslots; i++) {
202fcf3ce44SJohn Forte
203fcf3ce44SJohn Forte /*
204fcf3ce44SJohn Forte * Open SBus memory for this slot.
205fcf3ce44SJohn Forte */
206fcf3ce44SJohn Forte slotname = &sbus_list[i][0];
207fcf3ce44SJohn Forte if (fflag && (strcmp(slotname, bootpath) == 0)) {
208fcf3ce44SJohn Forte (void) fprintf(stderr,
209fcf3ce44SJohn Forte MSGSTR(4504, " Ignoring %s (bootpath)\n"), slotname);
210fcf3ce44SJohn Forte continue;
211fcf3ce44SJohn Forte }
212fcf3ce44SJohn Forte
213fcf3ce44SJohn Forte (void) sprintf(socal, "%s:0", &sbussoc_list[i][0]);
214fcf3ce44SJohn Forte
215fcf3ce44SJohn Forte if ((fd = open(socal, O_RDWR)) < 0) {
216fcf3ce44SJohn Forte (void) sprintf(socal, "%s:1", &sbussoc_list[i][0]);
217fcf3ce44SJohn Forte if ((fd = open(socal, O_RDWR)) < 0) {
218fcf3ce44SJohn Forte (void) fprintf(stderr,
219fcf3ce44SJohn Forte MSGSTR(4505, "Could not open %s\n"),
220fcf3ce44SJohn Forte &sbussoc_list[i][0]);
221fcf3ce44SJohn Forte (void) fprintf(stderr,
222fcf3ce44SJohn Forte MSGSTR(4506, "Ignoring %s\n"),
223fcf3ce44SJohn Forte &sbussoc_list[i][0]);
224fcf3ce44SJohn Forte retval++;
225fcf3ce44SJohn Forte continue;
226fcf3ce44SJohn Forte }
227fcf3ce44SJohn Forte }
228fcf3ce44SJohn Forte
229fcf3ce44SJohn Forte (void) close(fd);
230fcf3ce44SJohn Forte
231fcf3ce44SJohn Forte if (verbose) {
232fcf3ce44SJohn Forte (void) fprintf(stdout, "\n ");
233fcf3ce44SJohn Forte (void) fprintf(stdout,
234fcf3ce44SJohn Forte MSGSTR(85, "Opening %s\n"), slotname);
235fcf3ce44SJohn Forte }
236fcf3ce44SJohn Forte
237fcf3ce44SJohn Forte fd = open(slotname, O_RDWR);
238fcf3ce44SJohn Forte
239fcf3ce44SJohn Forte if (fd < 0) {
240fcf3ce44SJohn Forte perror(MSGSTR(4507, "open of slotname"));
241fcf3ce44SJohn Forte retval++;
242fcf3ce44SJohn Forte continue;
243fcf3ce44SJohn Forte }
244fcf3ce44SJohn Forte
245fcf3ce44SJohn Forte /*
246fcf3ce44SJohn Forte * Mmap that SBus memory into my memory space.
247fcf3ce44SJohn Forte */
248fcf3ce44SJohn Forte addr = mmap((caddr_t)0, PROM_SIZ_ROUNDED, PROT_READ|PROT_WRITE,
249fcf3ce44SJohn Forte MAP_SHARED, fd, 0);
250fcf3ce44SJohn Forte
251fcf3ce44SJohn Forte if (addr == MAP_FAILED) {
252fcf3ce44SJohn Forte perror(MSGSTR(46, "mmap"));
253fcf3ce44SJohn Forte (void) close(fd);
254fcf3ce44SJohn Forte retval++;
255fcf3ce44SJohn Forte continue;
256fcf3ce44SJohn Forte }
257fcf3ce44SJohn Forte
258fcf3ce44SJohn Forte if ((int)addr == -1) {
259fcf3ce44SJohn Forte perror(MSGSTR(46, "mmap"));
260fcf3ce44SJohn Forte (void) close(fd);
261fcf3ce44SJohn Forte retval++;
262fcf3ce44SJohn Forte continue;
263fcf3ce44SJohn Forte }
264fcf3ce44SJohn Forte
265fcf3ce44SJohn Forte regs = (socal_reg_t *)((int)addr + REG_OFFSET);
266fcf3ce44SJohn Forte
267fcf3ce44SJohn Forte (void) fprintf(stdout,
268fcf3ce44SJohn Forte MSGSTR(4508, "\n Device: %s\n"),
269fcf3ce44SJohn Forte &sbussoc_list[i][0]);
270fcf3ce44SJohn Forte /*
271fcf3ce44SJohn Forte * Load the New FCode
272fcf3ce44SJohn Forte */
273fcf3ce44SJohn Forte if (fflag) {
274fcf3ce44SJohn Forte if (!warn())
275fcf3ce44SJohn Forte retval += load_file(file, addr, regs);
276fcf3ce44SJohn Forte } else if (vflag) {
277fcf3ce44SJohn Forte if (findversion(i, (uchar_t *)&version[0]) == FOUND) {
278fcf3ce44SJohn Forte (void) fprintf(stdout,
279fcf3ce44SJohn Forte MSGSTR(4509,
280fcf3ce44SJohn Forte " Detected FC100/S Version: %s\n"), version);
281fcf3ce44SJohn Forte }
282fcf3ce44SJohn Forte }
283fcf3ce44SJohn Forte
284fcf3ce44SJohn Forte if (munmap(addr, PROM_SIZ) == -1) {
285fcf3ce44SJohn Forte perror(MSGSTR(4510, "munmap"));
286fcf3ce44SJohn Forte retval++;
287fcf3ce44SJohn Forte }
288fcf3ce44SJohn Forte
289fcf3ce44SJohn Forte (void) close(fd);
290fcf3ce44SJohn Forte
291fcf3ce44SJohn Forte }
292fcf3ce44SJohn Forte (void) fprintf(stdout, " ");
293fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(125, "Complete\n"));
294fcf3ce44SJohn Forte return (retval);
295fcf3ce44SJohn Forte }
296fcf3ce44SJohn Forte
297fcf3ce44SJohn Forte static int
findversion(int index,uchar_t * version)298fcf3ce44SJohn Forte findversion(int index, uchar_t *version)
299fcf3ce44SJohn Forte /*ARGSUSED*/
300fcf3ce44SJohn Forte {
301*e9175934SKlaus Ziegler int fd = 0, ntries;
302fcf3ce44SJohn Forte struct socal_fm_version *buffer;
303fcf3ce44SJohn Forte char socal[MAXNAMELEN];
304fcf3ce44SJohn Forte char fp[MAXNAMELEN];
305fcf3ce44SJohn Forte char prom_ver[100];
306fcf3ce44SJohn Forte char mcode_ver[100];
307fcf3ce44SJohn Forte uint_t dev_type;
308fcf3ce44SJohn Forte fcio_t fcio;
309fcf3ce44SJohn Forte char fw_rev[FC_FW_REV_SIZE + 1];
310fcf3ce44SJohn Forte
311fcf3ce44SJohn Forte
312fcf3ce44SJohn Forte if ((dev_type = g_get_path_type(&sbussoc_list[index][0])) == 0) {
313fcf3ce44SJohn Forte return (L_INVALID_PATH);
314fcf3ce44SJohn Forte }
315fcf3ce44SJohn Forte
316fcf3ce44SJohn Forte
317fcf3ce44SJohn Forte if (dev_type & FC4_FCA_MASK) {
318fcf3ce44SJohn Forte P_DPRINTF("findversion: found an FC4 path\n");
319fcf3ce44SJohn Forte (void) sprintf(socal, "%s:0", &sbussoc_list[index][0]);
320fcf3ce44SJohn Forte if ((fd = open(socal, O_RDWR)) < 0) {
321fcf3ce44SJohn Forte (void) sprintf(socal, "%s:1", &sbussoc_list[index][0]);
322fcf3ce44SJohn Forte if ((fd = open(socal, O_RDWR)) < 0) {
323fcf3ce44SJohn Forte (void) fprintf(stderr,
324fcf3ce44SJohn Forte MSGSTR(4511, "Could not open %s\n"),
325fcf3ce44SJohn Forte &sbussoc_list[index][0]);
326fcf3ce44SJohn Forte (void) close(fd);
327fcf3ce44SJohn Forte return (NOT_FOUND);
328fcf3ce44SJohn Forte }
329fcf3ce44SJohn Forte }
330fcf3ce44SJohn Forte if ((buffer = (struct socal_fm_version *)malloc(
331fcf3ce44SJohn Forte sizeof (struct socal_fm_version))) == NULL) {
332fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(10,
333fcf3ce44SJohn Forte " Error: Unable to allocate memory."));
334fcf3ce44SJohn Forte (void) fprintf(stderr, "\n");
335fcf3ce44SJohn Forte (void) close(fd);
336fcf3ce44SJohn Forte return (NOT_FOUND);
337fcf3ce44SJohn Forte }
338fcf3ce44SJohn Forte
339fcf3ce44SJohn Forte buffer->fcode_ver = (char *)version;
340fcf3ce44SJohn Forte buffer->mcode_ver = mcode_ver;
341fcf3ce44SJohn Forte buffer->prom_ver = prom_ver;
342fcf3ce44SJohn Forte buffer->fcode_ver_len = MAXNAMELEN - 1;
343fcf3ce44SJohn Forte buffer->mcode_ver_len = 100;
344fcf3ce44SJohn Forte buffer->prom_ver_len = 100;
345fcf3ce44SJohn Forte
346fcf3ce44SJohn Forte if (ioctl(fd, FCIO_FCODE_MCODE_VERSION, buffer) < 0) {
347fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4512,
348fcf3ce44SJohn Forte "fcal_s_download: could not get"
349fcf3ce44SJohn Forte " fcode version.\n"));
350fcf3ce44SJohn Forte (void) close(fd);
351fcf3ce44SJohn Forte (void) free(buffer);
352fcf3ce44SJohn Forte return (NOT_FOUND);
353fcf3ce44SJohn Forte }
354fcf3ce44SJohn Forte version[buffer->fcode_ver_len] = '\0';
355fcf3ce44SJohn Forte free(buffer);
356fcf3ce44SJohn Forte
357fcf3ce44SJohn Forte } else if (dev_type & FC_FCA_MASK) {
358fcf3ce44SJohn Forte /*
359fcf3ce44SJohn Forte * Get the fcode and prom's fw version
360fcf3ce44SJohn Forte * using new ioctls. Currently, we pass
361fcf3ce44SJohn Forte * only the fcode version to the calling function
362fcf3ce44SJohn Forte * and ignore the FW version (using the existing
363fcf3ce44SJohn Forte * implementation). The function definition
364fcf3ce44SJohn Forte * might be changed in future to pass both the
365fcf3ce44SJohn Forte * fcode and FW revisions to the calling function, if
366fcf3ce44SJohn Forte * needed by the calling function.
367fcf3ce44SJohn Forte */
368fcf3ce44SJohn Forte P_DPRINTF("findversion: found an FC path\n");
369fcf3ce44SJohn Forte (void) sprintf(fp, "%s/fp@0,0:devctl",
370fcf3ce44SJohn Forte &sbussoc_list[index][0]);
371fcf3ce44SJohn Forte if ((fd = open(fp, O_RDWR)) < 0) {
372fcf3ce44SJohn Forte (void) sprintf(fp, "%s/fp@1,0:devctl",
373fcf3ce44SJohn Forte &sbussoc_list[index][0]);
374fcf3ce44SJohn Forte if ((fd = open(fp, O_RDWR)) < 0) {
375fcf3ce44SJohn Forte (void) fprintf(stderr,
376fcf3ce44SJohn Forte MSGSTR(4511, "Could not open %s\n"),
377fcf3ce44SJohn Forte &sbussoc_list[index][0]);
378fcf3ce44SJohn Forte (void) close(fd);
379fcf3ce44SJohn Forte return (NOT_FOUND);
380fcf3ce44SJohn Forte }
381fcf3ce44SJohn Forte }
382fcf3ce44SJohn Forte /* Get the fcode version */
383fcf3ce44SJohn Forte bzero(version, sizeof (version));
384fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_FCODE_REV;
385fcf3ce44SJohn Forte /* Information read operation */
386fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ;
387fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)version;
388fcf3ce44SJohn Forte fcio.fcio_olen = MAXNAMELEN;
389fcf3ce44SJohn Forte
390fcf3ce44SJohn Forte for (ntries = 0; ntries < MAX_RETRIES; ntries++) {
391fcf3ce44SJohn Forte if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
392fcf3ce44SJohn Forte if ((errno == EAGAIN) &&
393fcf3ce44SJohn Forte (ntries+1 < MAX_RETRIES)) {
394fcf3ce44SJohn Forte /* wait 30 secs */
395fcf3ce44SJohn Forte (void) sleep(MAX_WAIT_TIME);
396fcf3ce44SJohn Forte continue;
397fcf3ce44SJohn Forte }
398fcf3ce44SJohn Forte I_DPRINTF("ioctl FCIO_GET_FCODE_REV failed.\n"
399fcf3ce44SJohn Forte "Error: %s\n", strerror(errno));
400fcf3ce44SJohn Forte (void) close(fd);
401fcf3ce44SJohn Forte return (L_FCIO_GET_FCODE_REV_FAIL);
402fcf3ce44SJohn Forte }
403fcf3ce44SJohn Forte break;
404fcf3ce44SJohn Forte }
405fcf3ce44SJohn Forte version[MAXNAMELEN-1] = '\0';
406fcf3ce44SJohn Forte
407fcf3ce44SJohn Forte /* Get the FW revision */
408fcf3ce44SJohn Forte bzero(fw_rev, sizeof (fw_rev));
409fcf3ce44SJohn Forte fcio.fcio_cmd = FCIO_GET_FW_REV;
410fcf3ce44SJohn Forte /* Information read operation */
411fcf3ce44SJohn Forte fcio.fcio_xfer = FCIO_XFER_READ;
412fcf3ce44SJohn Forte fcio.fcio_obuf = (caddr_t)fw_rev;
413fcf3ce44SJohn Forte fcio.fcio_olen = FC_FW_REV_SIZE;
414fcf3ce44SJohn Forte for (ntries = 0; ntries < MAX_RETRIES; ntries++) {
415fcf3ce44SJohn Forte if (ioctl(fd, FCIO_CMD, &fcio) != 0) {
416fcf3ce44SJohn Forte if ((errno == EAGAIN) &&
417fcf3ce44SJohn Forte (ntries+1 < MAX_RETRIES)) {
418fcf3ce44SJohn Forte /* wait 30 secs */
419fcf3ce44SJohn Forte (void) sleep(MAX_WAIT_TIME);
420fcf3ce44SJohn Forte continue;
421fcf3ce44SJohn Forte }
422fcf3ce44SJohn Forte I_DPRINTF(" FCIO_GET_FW_REV ioctl failed.\n"
423fcf3ce44SJohn Forte " Error: %s\n", strerror(errno));
424fcf3ce44SJohn Forte (void) close(fd);
425fcf3ce44SJohn Forte return (L_FCIO_GET_FW_REV_FAIL);
426fcf3ce44SJohn Forte }
427fcf3ce44SJohn Forte break;
428fcf3ce44SJohn Forte }
429fcf3ce44SJohn Forte }
430fcf3ce44SJohn Forte
431fcf3ce44SJohn Forte (void) close(fd);
432fcf3ce44SJohn Forte return (FOUND);
433fcf3ce44SJohn Forte }
434fcf3ce44SJohn Forte /*
435fcf3ce44SJohn Forte * program an FEprom with data from 'source_address'.
436fcf3ce44SJohn Forte * program the FEprom with zeroes,
437fcf3ce44SJohn Forte * erase it,
438fcf3ce44SJohn Forte * program it with the real data.
439fcf3ce44SJohn Forte */
440fcf3ce44SJohn Forte static int
feprom_program(uchar_t * source_address,uchar_t * dest_address,volatile socal_reg_t * regs)441fcf3ce44SJohn Forte feprom_program(uchar_t *source_address, uchar_t *dest_address,
442fcf3ce44SJohn Forte volatile socal_reg_t *regs)
443fcf3ce44SJohn Forte {
444fcf3ce44SJohn Forte int i;
445fcf3ce44SJohn Forte
446fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4513, "Filling with zeroes...\n"));
447fcf3ce44SJohn Forte if (!write_feprom((uchar_t *)0, dest_address, regs)) {
448fcf3ce44SJohn Forte (void) fprintf(stderr,
449fcf3ce44SJohn Forte MSGSTR(4514, "FEprom at 0x%x: zero fill failed\n"),
450fcf3ce44SJohn Forte (int)dest_address);
451fcf3ce44SJohn Forte return (0);
452fcf3ce44SJohn Forte }
453fcf3ce44SJohn Forte
454fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4515, "Erasing...\n"));
455fcf3ce44SJohn Forte for (i = 0; i < FEPROM_MAX_ERASE; i++) {
456fcf3ce44SJohn Forte if (feprom_erase(dest_address, regs))
457fcf3ce44SJohn Forte break;
458fcf3ce44SJohn Forte }
459fcf3ce44SJohn Forte
460fcf3ce44SJohn Forte if (i >= FEPROM_MAX_ERASE) {
461fcf3ce44SJohn Forte (void) fprintf(stderr,
462fcf3ce44SJohn Forte MSGSTR(4516, "FEprom at 0x%x: failed to erase\n"),
463fcf3ce44SJohn Forte (int)dest_address);
464fcf3ce44SJohn Forte return (0);
465fcf3ce44SJohn Forte } else if (i > 0) {
466fcf3ce44SJohn Forte if (i == 1) {
467fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4517,
468fcf3ce44SJohn Forte "FEprom erased after %d attempt\n"), i);
469fcf3ce44SJohn Forte } else {
470fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4518,
471fcf3ce44SJohn Forte "FEprom erased after %d attempts\n"), i);
472fcf3ce44SJohn Forte }
473fcf3ce44SJohn Forte }
474fcf3ce44SJohn Forte
475fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4519, "Programming...\n"));
476fcf3ce44SJohn Forte if (!(write_feprom(source_address, dest_address, regs))) {
477fcf3ce44SJohn Forte (void) fprintf(stderr,
478fcf3ce44SJohn Forte MSGSTR(4520, "FEprom at 0x%x: write failed\n"),
479fcf3ce44SJohn Forte (int)dest_address);
480fcf3ce44SJohn Forte return (0);
481fcf3ce44SJohn Forte }
482fcf3ce44SJohn Forte
483fcf3ce44SJohn Forte /* select the zeroth bank at end so we can read it */
484fcf3ce44SJohn Forte regs->socal_cr.w &= ~(0x30000);
485fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4521, "Programming done\n"));
486fcf3ce44SJohn Forte return (1);
487fcf3ce44SJohn Forte }
488fcf3ce44SJohn Forte
489fcf3ce44SJohn Forte /*
490fcf3ce44SJohn Forte * program an FEprom one byte at a time using hot electron injection.
491fcf3ce44SJohn Forte */
492fcf3ce44SJohn Forte static int
write_feprom(uchar_t * source_address,uchar_t * dest_address,volatile socal_reg_t * regs)493fcf3ce44SJohn Forte write_feprom(uchar_t *source_address, uchar_t *dest_address,
494fcf3ce44SJohn Forte volatile socal_reg_t *regs)
495fcf3ce44SJohn Forte {
496fcf3ce44SJohn Forte int pulse, i;
497fcf3ce44SJohn Forte uchar_t *s = source_address;
498fcf3ce44SJohn Forte volatile uchar_t *d;
499fcf3ce44SJohn Forte
500fcf3ce44SJohn Forte for (i = 0; i < FEPROM_SIZE; i++, s++) {
501fcf3ce44SJohn Forte
502fcf3ce44SJohn Forte if ((i & 0xffff) == 0) {
503fcf3ce44SJohn Forte (void) fprintf(stdout,
504fcf3ce44SJohn Forte MSGSTR(4522, "selecting bank %d\n"), i>>16);
505fcf3ce44SJohn Forte regs->socal_cr.w &= ~(0x30000);
506fcf3ce44SJohn Forte regs->socal_cr.w |= i & 0x30000;
507fcf3ce44SJohn Forte }
508fcf3ce44SJohn Forte
509fcf3ce44SJohn Forte d = dest_address + (i & 0xffff);
510fcf3ce44SJohn Forte
511fcf3ce44SJohn Forte for (pulse = 0; pulse < FEPROM_MAX_PROGRAM; pulse++) {
512fcf3ce44SJohn Forte *d = FEPROM_PROGRAM;
513fcf3ce44SJohn Forte *d = source_address ? *s : 0;
514fcf3ce44SJohn Forte usec_delay(50);
515fcf3ce44SJohn Forte *d = FEPROM_PROGRAM_VERIFY;
516fcf3ce44SJohn Forte usec_delay(30);
517fcf3ce44SJohn Forte if (*d == (source_address ? *s : 0))
518fcf3ce44SJohn Forte break;
519fcf3ce44SJohn Forte }
520fcf3ce44SJohn Forte
521fcf3ce44SJohn Forte if (pulse >= FEPROM_MAX_PROGRAM) {
522fcf3ce44SJohn Forte *dest_address = FEPROM_RESET;
523fcf3ce44SJohn Forte return (0);
524fcf3ce44SJohn Forte }
525fcf3ce44SJohn Forte }
526fcf3ce44SJohn Forte
527fcf3ce44SJohn Forte *dest_address = FEPROM_RESET;
528fcf3ce44SJohn Forte return (1);
529fcf3ce44SJohn Forte }
530fcf3ce44SJohn Forte
531fcf3ce44SJohn Forte /*
532fcf3ce44SJohn Forte * erase an FEprom using Fowler-Nordheim tunneling.
533fcf3ce44SJohn Forte */
534fcf3ce44SJohn Forte static int
feprom_erase(volatile uchar_t * dest_address,volatile socal_reg_t * regs)535fcf3ce44SJohn Forte feprom_erase(volatile uchar_t *dest_address, volatile socal_reg_t *regs)
536fcf3ce44SJohn Forte {
537fcf3ce44SJohn Forte int i;
538fcf3ce44SJohn Forte volatile uchar_t *d = dest_address;
539fcf3ce44SJohn Forte
540fcf3ce44SJohn Forte *d = FEPROM_ERASE;
541fcf3ce44SJohn Forte usec_delay(50);
542fcf3ce44SJohn Forte *d = FEPROM_ERASE;
543fcf3ce44SJohn Forte
544fcf3ce44SJohn Forte usec_delay(10000); /* wait 10ms while FEprom erases */
545fcf3ce44SJohn Forte
546fcf3ce44SJohn Forte for (i = 0; i < FEPROM_SIZE; i++) {
547fcf3ce44SJohn Forte
548fcf3ce44SJohn Forte if ((i & 0xffff) == 0) {
549fcf3ce44SJohn Forte regs->socal_cr.w &= ~(0x30000);
550fcf3ce44SJohn Forte regs->socal_cr.w |= i & 0x30000;
551fcf3ce44SJohn Forte }
552fcf3ce44SJohn Forte
553fcf3ce44SJohn Forte d = dest_address + (i & 0xffff);
554fcf3ce44SJohn Forte
555fcf3ce44SJohn Forte *d = FEPROM_ERASE_VERIFY;
556fcf3ce44SJohn Forte usec_delay(50);
557fcf3ce44SJohn Forte if (*d != 0xff) {
558fcf3ce44SJohn Forte *dest_address = FEPROM_RESET;
559fcf3ce44SJohn Forte return (0);
560fcf3ce44SJohn Forte }
561fcf3ce44SJohn Forte }
562fcf3ce44SJohn Forte *dest_address = FEPROM_RESET;
563fcf3ce44SJohn Forte return (1);
564fcf3ce44SJohn Forte }
565fcf3ce44SJohn Forte
566fcf3ce44SJohn Forte static void
usec_delay(int s)567fcf3ce44SJohn Forte usec_delay(int s)
568fcf3ce44SJohn Forte {
569fcf3ce44SJohn Forte hrtime_t now, then;
570fcf3ce44SJohn Forte
571fcf3ce44SJohn Forte now = gethrtime();
572fcf3ce44SJohn Forte then = now + s*1000;
573fcf3ce44SJohn Forte do {
574fcf3ce44SJohn Forte now = gethrtime();
575fcf3ce44SJohn Forte } while (now < then);
576fcf3ce44SJohn Forte }
577fcf3ce44SJohn Forte
578fcf3ce44SJohn Forte static uint_t
getsbuslist(void)579fcf3ce44SJohn Forte getsbuslist(void)
580fcf3ce44SJohn Forte {
581fcf3ce44SJohn Forte int devcnt = 0;
582fcf3ce44SJohn Forte char devpath[PATH_MAX];
583fcf3ce44SJohn Forte
584fcf3ce44SJohn Forte /* We're searching the /devices directory, so... */
585fcf3ce44SJohn Forte (void) strcpy(devpath, "/devices");
586fcf3ce44SJohn Forte
587fcf3ce44SJohn Forte /* get the directory entries under /devices for socal sbusmem */
588fcf3ce44SJohn Forte (void) getsocpath(devpath, (int *)&devcnt);
589fcf3ce44SJohn Forte
590fcf3ce44SJohn Forte return (devcnt);
591fcf3ce44SJohn Forte }
592fcf3ce44SJohn Forte
593fcf3ce44SJohn Forte static void
getbootdev(unsigned int verbose)594fcf3ce44SJohn Forte getbootdev(unsigned int verbose)
595fcf3ce44SJohn Forte {
596fcf3ce44SJohn Forte char *df = "df /";
597fcf3ce44SJohn Forte FILE *ptr;
598*e9175934SKlaus Ziegler char *p = NULL, *p1;
599fcf3ce44SJohn Forte char bootdev[PATH_MAX];
600fcf3ce44SJohn Forte char buf[BUFSIZ];
601fcf3ce44SJohn Forte int foundroot = 0;
602fcf3ce44SJohn Forte
603fcf3ce44SJohn Forte
604fcf3ce44SJohn Forte if ((ptr = popen(df, "r")) != NULL) {
605fcf3ce44SJohn Forte while (fgets(buf, BUFSIZ, ptr) != NULL) {
606fcf3ce44SJohn Forte if (p = strstr(buf, "/dev/dsk/")) {
607fcf3ce44SJohn Forte (void) memset((char *)&bootdev[0], 0,
608fcf3ce44SJohn Forte PATH_MAX);
609fcf3ce44SJohn Forte p1 = p;
610fcf3ce44SJohn Forte while (*p1 != '\0') {
611fcf3ce44SJohn Forte if (!isalnum(*p1) && (*p1 != '/'))
612fcf3ce44SJohn Forte *p1 = ' ';
613fcf3ce44SJohn Forte p1++;
614fcf3ce44SJohn Forte }
615fcf3ce44SJohn Forte (void) sscanf(p, "%s", bootdev);
616fcf3ce44SJohn Forte foundroot = 1;
617fcf3ce44SJohn Forte }
618fcf3ce44SJohn Forte }
619fcf3ce44SJohn Forte if (!foundroot) {
620fcf3ce44SJohn Forte if (verbose)
621fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(44,
622fcf3ce44SJohn Forte "root is not on a local disk!\n"));
623fcf3ce44SJohn Forte (void) memset((char *)&bootpath[0], 0, PATH_MAX);
624fcf3ce44SJohn Forte return;
625fcf3ce44SJohn Forte }
626fcf3ce44SJohn Forte (void) pclose(ptr);
627fcf3ce44SJohn Forte if (bootdev[0]) {
628fcf3ce44SJohn Forte char *ls;
629fcf3ce44SJohn Forte char *p1;
630fcf3ce44SJohn Forte char *p2 = NULL;
631fcf3ce44SJohn Forte char *sbusmem = "/sbusmem@";
632fcf3ce44SJohn Forte char *slot = ",0:slot";
633fcf3ce44SJohn Forte
634fcf3ce44SJohn Forte ls = (char *)malloc(PATH_MAX);
635525fef19SToomas Soome (void) memset((char *)ls, 0, PATH_MAX);
636fcf3ce44SJohn Forte (void) strcpy(ls, "ls -l ");
637fcf3ce44SJohn Forte (void) strcat(ls, bootdev);
638fcf3ce44SJohn Forte if ((ptr = popen(ls, "r")) != NULL) {
639fcf3ce44SJohn Forte while (fgets(buf, BUFSIZ, ptr) != NULL) {
640fcf3ce44SJohn Forte if (p = strstr(buf, "/devices")) {
641fcf3ce44SJohn Forte if (p1 = strstr(buf, "sbus")) {
642fcf3ce44SJohn Forte while (*p1 != '/')
643fcf3ce44SJohn Forte p1++;
644fcf3ce44SJohn Forte p2 = strstr(p1, "@");
645fcf3ce44SJohn Forte ++p2;
646fcf3ce44SJohn Forte *p1 = '\0';
647fcf3ce44SJohn Forte } else {
648fcf3ce44SJohn Forte if (p1 = strstr(buf,
649fcf3ce44SJohn Forte SOCAL_STR)) {
650fcf3ce44SJohn Forte p2 = strstr(p1, "@");
651fcf3ce44SJohn Forte ++p2;
652fcf3ce44SJohn Forte --p1;
653fcf3ce44SJohn Forte *p1 = '\0';
654fcf3ce44SJohn Forte }
655fcf3ce44SJohn Forte }
656fcf3ce44SJohn Forte }
657fcf3ce44SJohn Forte }
658fcf3ce44SJohn Forte (void) pclose(ptr);
659fcf3ce44SJohn Forte }
660fcf3ce44SJohn Forte (void) memset((char *)&bootdev[0], 0, PATH_MAX);
661fcf3ce44SJohn Forte (void) sscanf(p, "%s", bootdev);
662fcf3ce44SJohn Forte (void) memset((char *)&bootpath[0], 0, PATH_MAX);
663fcf3ce44SJohn Forte (void) strcat(bootpath, bootdev);
664fcf3ce44SJohn Forte (void) strcat(bootpath, sbusmem);
665fcf3ce44SJohn Forte if (p2) {
666fcf3ce44SJohn Forte (void) strncat(bootpath, p2, 1);
667fcf3ce44SJohn Forte (void) strcat(bootpath, slot);
668fcf3ce44SJohn Forte (void) strncat(bootpath, p2, 1);
669fcf3ce44SJohn Forte }
670fcf3ce44SJohn Forte }
671fcf3ce44SJohn Forte }
672fcf3ce44SJohn Forte }
673fcf3ce44SJohn Forte
674fcf3ce44SJohn Forte /*
675fcf3ce44SJohn Forte * This function reads "size" bytes from the FC100/S PROM.
676fcf3ce44SJohn Forte * source_address: PROM address
677fcf3ce44SJohn Forte * dest_address: local memeory
678fcf3ce44SJohn Forte * offset: Location in PROM to start reading from.
679fcf3ce44SJohn Forte */
680fcf3ce44SJohn Forte static void
feprom_read(uchar_t * source_address,uchar_t * dest_address,int offset,int size,volatile socal_reg_t * regs)681fcf3ce44SJohn Forte feprom_read(uchar_t *source_address, uchar_t *dest_address,
682fcf3ce44SJohn Forte int offset, int size, volatile socal_reg_t *regs)
683fcf3ce44SJohn Forte {
684fcf3ce44SJohn Forte uchar_t *s = source_address;
685fcf3ce44SJohn Forte uchar_t *d = dest_address;
686fcf3ce44SJohn Forte int i = offset;
687fcf3ce44SJohn Forte
688fcf3ce44SJohn Forte if (getenv("_LUX_D_DEBUG") != NULL) {
689fcf3ce44SJohn Forte (void) fprintf(stdout,
690fcf3ce44SJohn Forte " feprom_read: selecting bank %d\n",
691fcf3ce44SJohn Forte (i&0xf0000)>>16);
692fcf3ce44SJohn Forte if (size <= 8) {
693fcf3ce44SJohn Forte (void) fprintf(stdout, " Data read: ");
694fcf3ce44SJohn Forte }
695fcf3ce44SJohn Forte }
696fcf3ce44SJohn Forte regs->socal_cr.w = i & 0xf0000;
697fcf3ce44SJohn Forte s = source_address + (i & 0xffff);
698fcf3ce44SJohn Forte *s = FEPROM_READ_MEMORY;
699fcf3ce44SJohn Forte usec_delay(6);
700fcf3ce44SJohn Forte for (; s < source_address + (i & 0xffff) + size; d++, s++) {
701fcf3ce44SJohn Forte *d = *s;
702fcf3ce44SJohn Forte if ((getenv("_LUX_D_DEBUG") != NULL) &&
703fcf3ce44SJohn Forte (size <= 8)) {
704fcf3ce44SJohn Forte (void) fprintf(stdout, "0x%x ", *d);
705fcf3ce44SJohn Forte }
706fcf3ce44SJohn Forte }
707fcf3ce44SJohn Forte if ((getenv("_LUX_D_DEBUG") != NULL) &&
708fcf3ce44SJohn Forte (size <= 8)) {
709fcf3ce44SJohn Forte (void) fprintf(stdout, "\n From offset: 0x%x\n",
710fcf3ce44SJohn Forte offset);
711fcf3ce44SJohn Forte }
712fcf3ce44SJohn Forte }
713fcf3ce44SJohn Forte
714fcf3ce44SJohn Forte
715fcf3ce44SJohn Forte static int
load_file(char * file,caddr_t prom,volatile socal_reg_t * regs)716fcf3ce44SJohn Forte load_file(char *file, caddr_t prom, volatile socal_reg_t *regs)
717fcf3ce44SJohn Forte {
718fcf3ce44SJohn Forte uint_t wwn_d8, wwn_lo;
719fcf3ce44SJohn Forte uint_t wwn_hi;
720fcf3ce44SJohn Forte int ffd = open(file, 0);
721fcf3ce44SJohn Forte
722fcf3ce44SJohn Forte wwn_hi = FEPROM_SUN_WWN;
723fcf3ce44SJohn Forte
724fcf3ce44SJohn Forte if (ffd < 0) {
725fcf3ce44SJohn Forte perror(MSGSTR(4524, "open of file"));
726fcf3ce44SJohn Forte exit(1);
727fcf3ce44SJohn Forte }
728fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4525, "Loading FCode: %s\n"), file);
729fcf3ce44SJohn Forte
730fcf3ce44SJohn Forte if (read(ffd, &exec, sizeof (exec)) != sizeof (exec)) {
731fcf3ce44SJohn Forte perror(MSGSTR(4526, "read exec"));
732fcf3ce44SJohn Forte exit(1);
733fcf3ce44SJohn Forte }
734fcf3ce44SJohn Forte
735fcf3ce44SJohn Forte if (exec.a_trsize || exec.a_drsize) {
736fcf3ce44SJohn Forte (void) fprintf(stderr,
737fcf3ce44SJohn Forte MSGSTR(4527, "%s: is relocatable\n"), file);
738fcf3ce44SJohn Forte exit(1);
739fcf3ce44SJohn Forte }
740fcf3ce44SJohn Forte
741fcf3ce44SJohn Forte if (exec.a_data || exec.a_bss) {
742fcf3ce44SJohn Forte (void) fprintf(stderr,
743fcf3ce44SJohn Forte MSGSTR(4528, "%s: has data or bss\n"), file);
744fcf3ce44SJohn Forte exit(1);
745fcf3ce44SJohn Forte }
746fcf3ce44SJohn Forte
747fcf3ce44SJohn Forte if (exec.a_machtype != M_SPARC) {
748fcf3ce44SJohn Forte (void) fprintf(stderr,
749fcf3ce44SJohn Forte MSGSTR(4529, "%s: not for SPARC\n"), file);
750fcf3ce44SJohn Forte exit(1);
751fcf3ce44SJohn Forte }
752fcf3ce44SJohn Forte
753fcf3ce44SJohn Forte (void) fprintf(stdout, MSGSTR(4530,
754fcf3ce44SJohn Forte "Loading 0x%x bytes from %s at offset 0x%x\n"),
755fcf3ce44SJohn Forte (int)exec.a_text, file, 0);
756fcf3ce44SJohn Forte
757fcf3ce44SJohn Forte if (read(ffd, &buffer, exec.a_text) != exec.a_text) {
758fcf3ce44SJohn Forte perror(MSGSTR(4531, "read"));
759fcf3ce44SJohn Forte exit(1);
760fcf3ce44SJohn Forte }
761fcf3ce44SJohn Forte
762fcf3ce44SJohn Forte (void) close(ffd);
763fcf3ce44SJohn Forte
764fcf3ce44SJohn Forte feprom_read((uchar_t *)prom, (uchar_t *)&wwn_d8,
765fcf3ce44SJohn Forte FEPROM_WWN_OFFSET, 4, regs);
766fcf3ce44SJohn Forte feprom_read((uchar_t *)prom, (uchar_t *)&wwn_lo,
767fcf3ce44SJohn Forte FEPROM_WWN_OFFSET + 4, 4, regs);
768fcf3ce44SJohn Forte wwn_hi |= wwn_d8 & 0x0f; /* only last digit is interesting */
769fcf3ce44SJohn Forte if (getenv("_LUX_D_DEBUG") != NULL) {
770fcf3ce44SJohn Forte (void) fprintf(stdout,
771fcf3ce44SJohn Forte " load_file: Writing WWN hi:0x%x lo:0x%x "
772fcf3ce44SJohn Forte "to the FC100/S PROM\n", wwn_hi, wwn_lo);
773fcf3ce44SJohn Forte }
774fcf3ce44SJohn Forte /* put wwn into buffer location */
775fcf3ce44SJohn Forte bcopy((const void *)&wwn_hi,
776fcf3ce44SJohn Forte (void *)&buffer[FEPROM_WWN_OFFSET],
777fcf3ce44SJohn Forte sizeof (wwn_hi));
778fcf3ce44SJohn Forte bcopy((const void *)&wwn_lo,
779fcf3ce44SJohn Forte (void *)&buffer[FEPROM_WWN_OFFSET + 4],
780fcf3ce44SJohn Forte sizeof (wwn_lo));
781fcf3ce44SJohn Forte bcopy((const void *)&wwn_hi,
782fcf3ce44SJohn Forte (void *)&buffer[FEPROM_WWN_OFFSET + 8],
783fcf3ce44SJohn Forte sizeof (wwn_hi));
784fcf3ce44SJohn Forte bcopy((const void *)&wwn_lo,
785fcf3ce44SJohn Forte (void *)&buffer[FEPROM_WWN_OFFSET + 0xc],
786fcf3ce44SJohn Forte sizeof (wwn_lo));
787fcf3ce44SJohn Forte
788fcf3ce44SJohn Forte if (feprom_program((uchar_t *)buffer, (uchar_t *)prom, regs) == 0) {
789fcf3ce44SJohn Forte /* here 0 means failure */
790fcf3ce44SJohn Forte return (1);
791fcf3ce44SJohn Forte }
792fcf3ce44SJohn Forte
793fcf3ce44SJohn Forte return (0);
794fcf3ce44SJohn Forte }
795fcf3ce44SJohn Forte
796fcf3ce44SJohn Forte static int
warn(void)797fcf3ce44SJohn Forte warn(void)
798fcf3ce44SJohn Forte {
799fcf3ce44SJohn Forte char input[1024];
800fcf3ce44SJohn Forte
801fcf3ce44SJohn Forte input[0] = '\0';
802fcf3ce44SJohn Forte
803fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4532,
804fcf3ce44SJohn Forte "\nWARNING!! This program will update the FCode in this FC100/S Sbus Card.\n"));
805fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4533,
806fcf3ce44SJohn Forte "This may take a few (5) minutes. Please be patient.\n"));
807fcf3ce44SJohn Forte
808fcf3ce44SJohn Forte loop1:
809fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4534,
810fcf3ce44SJohn Forte "Do you wish to continue ? (y/n) "));
811fcf3ce44SJohn Forte
812fcf3ce44SJohn Forte (void) gets(input);
813fcf3ce44SJohn Forte
814fcf3ce44SJohn Forte if ((strcmp(input, MSGSTR(4535, "y")) == 0) ||
815fcf3ce44SJohn Forte (strcmp(input, MSGSTR(40, "yes")) == 0)) {
816fcf3ce44SJohn Forte return (FOUND);
817fcf3ce44SJohn Forte } else if ((strcmp(input, MSGSTR(4536, "n")) == 0) ||
818fcf3ce44SJohn Forte (strcmp(input, MSGSTR(45, "no")) == 0)) {
819fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4537, "Not Downloading FCode\n"));
820fcf3ce44SJohn Forte return (NOT_FOUND);
821fcf3ce44SJohn Forte } else {
822fcf3ce44SJohn Forte (void) fprintf(stderr, MSGSTR(4538, "Invalid input\n"));
823fcf3ce44SJohn Forte goto loop1;
824fcf3ce44SJohn Forte }
825fcf3ce44SJohn Forte }
826fcf3ce44SJohn Forte
827fcf3ce44SJohn Forte
828fcf3ce44SJohn Forte /*
829fcf3ce44SJohn Forte * getsocpath():
830525fef19SToomas Soome * Searches the /devices directory recursively returning all soc_name
831fcf3ce44SJohn Forte * entries in sbussoc_list (global). This excludes port entries and
832525fef19SToomas Soome * onboard socal (which leaves only directory entries with
833fcf3ce44SJohn Forte * soc_name included). devcnt is updated to reflect number of soc_name
834fcf3ce44SJohn Forte * devices found.
835fcf3ce44SJohn Forte */
836fcf3ce44SJohn Forte
837fcf3ce44SJohn Forte static void
getsocpath(char * devpath,int * devcnt)838fcf3ce44SJohn Forte getsocpath(char *devpath, int *devcnt)
839fcf3ce44SJohn Forte {
840fcf3ce44SJohn Forte struct stat statbuf;
841fcf3ce44SJohn Forte struct dirent *dirp;
842fcf3ce44SJohn Forte DIR *dp;
843fcf3ce44SJohn Forte char *ptr;
844fcf3ce44SJohn Forte
845fcf3ce44SJohn Forte if (lstat(devpath, &statbuf) < 0) {
846fcf3ce44SJohn Forte (void) fprintf(stderr,
847fcf3ce44SJohn Forte MSGSTR(4539, "Error: %s lstat() error\n"), devpath);
848fcf3ce44SJohn Forte exit(1);
849fcf3ce44SJohn Forte }
850fcf3ce44SJohn Forte
851fcf3ce44SJohn Forte if (S_ISDIR(statbuf.st_mode) == 0)
852fcf3ce44SJohn Forte /*
853fcf3ce44SJohn Forte * not a directory so
854fcf3ce44SJohn Forte * we don't care about it - return
855fcf3ce44SJohn Forte */
856fcf3ce44SJohn Forte return;
857fcf3ce44SJohn Forte
858fcf3ce44SJohn Forte else {
859fcf3ce44SJohn Forte if (strstr(devpath, ONBOARD_SOCAL))
860fcf3ce44SJohn Forte return;
861fcf3ce44SJohn Forte
862fcf3ce44SJohn Forte if (strstr(devpath, SOCAL_STR)) {
863fcf3ce44SJohn Forte /* It's a keeper - call the load function */
864fcf3ce44SJohn Forte if ((loadsocpath(devpath, devcnt)) < 0) {
865fcf3ce44SJohn Forte (void) fprintf(stderr,
866fcf3ce44SJohn Forte MSGSTR(4540, "Error: Cannot set device list\n"),
867fcf3ce44SJohn Forte devpath);
868fcf3ce44SJohn Forte exit(1);
869fcf3ce44SJohn Forte }
870fcf3ce44SJohn Forte /*
871fcf3ce44SJohn Forte * if socal directory - return,
872fcf3ce44SJohn Forte * nothing else to see here
873fcf3ce44SJohn Forte */
874fcf3ce44SJohn Forte return;
875fcf3ce44SJohn Forte }
876fcf3ce44SJohn Forte }
877fcf3ce44SJohn Forte
878fcf3ce44SJohn Forte /*
879fcf3ce44SJohn Forte * It's a directory. Call ourself to
880fcf3ce44SJohn Forte * traverse the path(s)
881fcf3ce44SJohn Forte */
882fcf3ce44SJohn Forte
883fcf3ce44SJohn Forte ptr = devpath + strlen(devpath);
884fcf3ce44SJohn Forte *ptr++ = '/';
885fcf3ce44SJohn Forte *ptr = 0;
886fcf3ce44SJohn Forte
887fcf3ce44SJohn Forte /* Forget the /devices/pseudo/ directory */
888fcf3ce44SJohn Forte if (strcmp(devpath, "/devices/pseudo/") == 0)
889fcf3ce44SJohn Forte return;
890fcf3ce44SJohn Forte
891fcf3ce44SJohn Forte if ((dp = opendir(devpath)) == NULL) {
892fcf3ce44SJohn Forte (void) fprintf(stderr,
893fcf3ce44SJohn Forte MSGSTR(4541, "Error: %s Can't read directory\n"), devpath);
894fcf3ce44SJohn Forte exit(1);
895fcf3ce44SJohn Forte }
896fcf3ce44SJohn Forte
897fcf3ce44SJohn Forte while ((dirp = readdir(dp)) != NULL) {
898fcf3ce44SJohn Forte
899fcf3ce44SJohn Forte if (strcmp(dirp->d_name, ".") == 0 ||
900fcf3ce44SJohn Forte strcmp(dirp->d_name, "..") == 0)
901fcf3ce44SJohn Forte continue;
902fcf3ce44SJohn Forte
903fcf3ce44SJohn Forte (void) strcpy(ptr, dirp->d_name); /* append name */
904fcf3ce44SJohn Forte getsocpath(devpath, devcnt);
905fcf3ce44SJohn Forte }
906fcf3ce44SJohn Forte
907fcf3ce44SJohn Forte if (closedir(dp) < 0) {
908fcf3ce44SJohn Forte (void) fprintf(stderr,
909fcf3ce44SJohn Forte MSGSTR(4542, "Error: %s Can't close directory\n"), devpath);
910fcf3ce44SJohn Forte exit(1);
911fcf3ce44SJohn Forte }
912fcf3ce44SJohn Forte }
913fcf3ce44SJohn Forte
914fcf3ce44SJohn Forte static int
loadsocpath(const char * pathname,int * devcnt)915fcf3ce44SJohn Forte loadsocpath(const char *pathname, int *devcnt)
916fcf3ce44SJohn Forte {
917fcf3ce44SJohn Forte int ret = 0;
918fcf3ce44SJohn Forte int len;
919fcf3ce44SJohn Forte int len_tmp;
920*e9175934SKlaus Ziegler char *sp = NULL;
921fcf3ce44SJohn Forte char *sp_tmp;
922fcf3ce44SJohn Forte char buffer[PATH_MAX];
923fcf3ce44SJohn Forte
924fcf3ce44SJohn Forte
925fcf3ce44SJohn Forte /*
926fcf3ce44SJohn Forte * Okay we found a device, now let's load it in to sbussoc_list
927fcf3ce44SJohn Forte * and load the sbusmem file into sbus_list
928fcf3ce44SJohn Forte */
929fcf3ce44SJohn Forte
930fcf3ce44SJohn Forte if (pathname != NULL && *devcnt < HBA_MAX) {
931fcf3ce44SJohn Forte (void) strcpy(sbussoc_list[*devcnt], pathname);
932fcf3ce44SJohn Forte if (sp_tmp = strstr(sbussoc_list[*devcnt], SOCAL_STR)) {
933fcf3ce44SJohn Forte sp = sp_tmp;
934fcf3ce44SJohn Forte /* len_tmp will be len of "SUNW,socal@" */
935fcf3ce44SJohn Forte len_tmp = SOCAL_STR_LEN + 1;
936fcf3ce44SJohn Forte }
937fcf3ce44SJohn Forte len = strlen(sbussoc_list[*devcnt]) - strlen(sp);
938fcf3ce44SJohn Forte (void) strncpy(buffer, sbussoc_list[*devcnt], len);
939fcf3ce44SJohn Forte buffer[len] = '\0';
940fcf3ce44SJohn Forte sp += len_tmp;
941fcf3ce44SJohn Forte (void) sprintf(sbus_list[*devcnt], "%ssbusmem@%c,0:slot%c",
942fcf3ce44SJohn Forte buffer, sp[0], sp[0]);
943fcf3ce44SJohn Forte *devcnt += 1;
944fcf3ce44SJohn Forte }
945fcf3ce44SJohn Forte else
946fcf3ce44SJohn Forte ret = -1;
947fcf3ce44SJohn Forte return (ret);
948fcf3ce44SJohn Forte }
949