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 #include "FCSyseventBridge.h"
27fcf3ce44SJohn Forte #include "Exceptions.h"
28fcf3ce44SJohn Forte #include "Trace.h"
29fcf3ce44SJohn Forte #include "AdapterAddEvent.h"
30fcf3ce44SJohn Forte #include "AdapterEvent.h"
31fcf3ce44SJohn Forte #include "AdapterPortEvent.h"
32fcf3ce44SJohn Forte #include "AdapterDeviceEvent.h"
33fcf3ce44SJohn Forte #include "TargetEvent.h"
34fcf3ce44SJohn Forte #include "sun_fc.h"
35fcf3ce44SJohn Forte #include <libnvpair.h>
36fcf3ce44SJohn Forte #include <iostream>
37*f3aaec0aSRichard Lowe #include <climits>
38fcf3ce44SJohn Forte 
39fcf3ce44SJohn Forte using namespace std;
40fcf3ce44SJohn Forte 
41fcf3ce44SJohn Forte FCSyseventBridge* FCSyseventBridge::_instance = NULL;
42fcf3ce44SJohn Forte 
getInstance()43fcf3ce44SJohn Forte FCSyseventBridge* FCSyseventBridge::getInstance() {
44fcf3ce44SJohn Forte     Trace log("FCSyseventBridge::getInstance");
45fcf3ce44SJohn Forte     if (_instance == NULL) {
46fcf3ce44SJohn Forte 	_instance = new FCSyseventBridge();
47fcf3ce44SJohn Forte     }
48fcf3ce44SJohn Forte     return (_instance);
49fcf3ce44SJohn Forte 
50fcf3ce44SJohn Forte }
51fcf3ce44SJohn Forte 
52fcf3ce44SJohn Forte 
addListener(AdapterAddEventListener * listener)53fcf3ce44SJohn Forte void FCSyseventBridge::addListener(AdapterAddEventListener *listener) {
54fcf3ce44SJohn Forte     lock();
55fcf3ce44SJohn Forte     try {
56fcf3ce44SJohn Forte 	adapterAddEventListeners.insert(adapterAddEventListeners.begin(),
57fcf3ce44SJohn Forte 		listener);
58fcf3ce44SJohn Forte 	validateRegistration();
59fcf3ce44SJohn Forte 	unlock();
60fcf3ce44SJohn Forte     } catch (...) {
61fcf3ce44SJohn Forte 	unlock();
62fcf3ce44SJohn Forte 	throw;
63fcf3ce44SJohn Forte     }
64fcf3ce44SJohn Forte }
addListener(AdapterEventListener * listener,HBA * hba)65fcf3ce44SJohn Forte void FCSyseventBridge::addListener(AdapterEventListener *listener, HBA *hba) {
66fcf3ce44SJohn Forte     lock();
67fcf3ce44SJohn Forte     try {
68fcf3ce44SJohn Forte 	adapterEventListeners.insert(adapterEventListeners.begin(), listener);
69fcf3ce44SJohn Forte 	validateRegistration();
70fcf3ce44SJohn Forte 	unlock();
71fcf3ce44SJohn Forte     } catch (...) {
72fcf3ce44SJohn Forte 	unlock();
73fcf3ce44SJohn Forte 	throw;
74fcf3ce44SJohn Forte     }
75fcf3ce44SJohn Forte }
addListener(AdapterPortEventListener * listener,HBAPort * port)76fcf3ce44SJohn Forte void FCSyseventBridge::addListener(AdapterPortEventListener *listener,
77fcf3ce44SJohn Forte 	    HBAPort *port) {
78fcf3ce44SJohn Forte     lock();
79fcf3ce44SJohn Forte     try {
80fcf3ce44SJohn Forte 	adapterPortEventListeners.insert(adapterPortEventListeners.begin(),
81fcf3ce44SJohn Forte 		listener);
82fcf3ce44SJohn Forte 	validateRegistration();
83fcf3ce44SJohn Forte 	unlock();
84fcf3ce44SJohn Forte     } catch (...) {
85fcf3ce44SJohn Forte 	unlock();
86fcf3ce44SJohn Forte 	throw;
87fcf3ce44SJohn Forte     }
88fcf3ce44SJohn Forte }
addListener(AdapterDeviceEventListener * listener,HBAPort * port)89fcf3ce44SJohn Forte void FCSyseventBridge::addListener(AdapterDeviceEventListener *listener,
90fcf3ce44SJohn Forte     HBAPort *port) {
91fcf3ce44SJohn Forte 	lock();
92fcf3ce44SJohn Forte 	try {
93fcf3ce44SJohn Forte 		adapterDeviceEventListeners.insert(adapterDeviceEventListeners.begin(),
94fcf3ce44SJohn Forte 		    listener);
95fcf3ce44SJohn Forte 		validateRegistration();
96fcf3ce44SJohn Forte 		unlock();
97fcf3ce44SJohn Forte 	} catch (...) {
98fcf3ce44SJohn Forte 		unlock();
99fcf3ce44SJohn Forte 		throw;
100fcf3ce44SJohn Forte 	}
101fcf3ce44SJohn Forte }
addListener(TargetEventListener * listener,HBAPort * port,uint64_t targetWWN,bool filter)102fcf3ce44SJohn Forte void FCSyseventBridge::addListener(TargetEventListener *listener,
103fcf3ce44SJohn Forte 	    HBAPort *port, uint64_t targetWWN, bool filter) {
104fcf3ce44SJohn Forte     lock();
105fcf3ce44SJohn Forte     try {
106fcf3ce44SJohn Forte 	targetEventListeners.insert(targetEventListeners.begin(), listener);
107fcf3ce44SJohn Forte 	validateRegistration();
108fcf3ce44SJohn Forte 	unlock();
109fcf3ce44SJohn Forte     } catch (...) {
110fcf3ce44SJohn Forte 	unlock();
111fcf3ce44SJohn Forte 	throw;
112fcf3ce44SJohn Forte     }
113fcf3ce44SJohn Forte }
114fcf3ce44SJohn Forte 
removeListener(AdapterAddEventListener * listener)115fcf3ce44SJohn Forte void FCSyseventBridge::removeListener(AdapterAddEventListener *listener) {
116fcf3ce44SJohn Forte     lock();
117fcf3ce44SJohn Forte     try {
118fcf3ce44SJohn Forte 	typedef vector<AdapterAddEventListener *>::iterator Iter;
119fcf3ce44SJohn Forte 	for (Iter tmp = adapterAddEventListeners.begin();
120fcf3ce44SJohn Forte 		tmp != adapterAddEventListeners.end(); tmp++) {
121fcf3ce44SJohn Forte 	    if (*tmp == listener) {
122fcf3ce44SJohn Forte 		adapterAddEventListeners.erase(tmp);
123fcf3ce44SJohn Forte 		unlock();
124fcf3ce44SJohn Forte 		return;
125fcf3ce44SJohn Forte 	    }
126fcf3ce44SJohn Forte 	}
127fcf3ce44SJohn Forte 	throw InvalidHandleException();
128fcf3ce44SJohn Forte     } catch (...) {
129fcf3ce44SJohn Forte 	unlock();
130fcf3ce44SJohn Forte 	throw;
131fcf3ce44SJohn Forte     }
132fcf3ce44SJohn Forte }
133fcf3ce44SJohn Forte 
removeListener(AdapterEventListener * listener)134fcf3ce44SJohn Forte void FCSyseventBridge::removeListener(AdapterEventListener *listener) {
135fcf3ce44SJohn Forte     lock();
136fcf3ce44SJohn Forte     try {
137fcf3ce44SJohn Forte 	typedef vector<AdapterEventListener *>::iterator Iter;
138fcf3ce44SJohn Forte 	for (Iter tmp = adapterEventListeners.begin();
139fcf3ce44SJohn Forte 		tmp != adapterEventListeners.end(); tmp++) {
140fcf3ce44SJohn Forte 	    if (*tmp == listener) {
141fcf3ce44SJohn Forte 		adapterEventListeners.erase(tmp);
142fcf3ce44SJohn Forte 		unlock();
143fcf3ce44SJohn Forte 		return;
144fcf3ce44SJohn Forte 	    }
145fcf3ce44SJohn Forte 	}
146fcf3ce44SJohn Forte 	throw InvalidHandleException();
147fcf3ce44SJohn Forte     } catch (...) {
148fcf3ce44SJohn Forte 	unlock();
149fcf3ce44SJohn Forte 	throw;
150fcf3ce44SJohn Forte     }
151fcf3ce44SJohn Forte }
152fcf3ce44SJohn Forte 
removeListener(AdapterPortEventListener * listener)153fcf3ce44SJohn Forte void FCSyseventBridge::removeListener(AdapterPortEventListener *listener) {
154fcf3ce44SJohn Forte     lock();
155fcf3ce44SJohn Forte     try {
156fcf3ce44SJohn Forte 	typedef vector<AdapterPortEventListener *>::iterator Iter;
157fcf3ce44SJohn Forte 	for (Iter tmp = adapterPortEventListeners.begin();
158fcf3ce44SJohn Forte 		tmp != adapterPortEventListeners.end(); tmp++) {
159fcf3ce44SJohn Forte 	    if (*tmp == listener) {
160fcf3ce44SJohn Forte 		adapterPortEventListeners.erase(tmp);
161fcf3ce44SJohn Forte 		unlock();
162fcf3ce44SJohn Forte 		return;
163fcf3ce44SJohn Forte 	    }
164fcf3ce44SJohn Forte 	}
165fcf3ce44SJohn Forte 	throw InvalidHandleException();
166fcf3ce44SJohn Forte     } catch (...) {
167fcf3ce44SJohn Forte 	unlock();
168fcf3ce44SJohn Forte 	throw;
169fcf3ce44SJohn Forte     }
170fcf3ce44SJohn Forte }
171fcf3ce44SJohn Forte 
removeListener(AdapterDeviceEventListener * listener)172fcf3ce44SJohn Forte void FCSyseventBridge::removeListener(AdapterDeviceEventListener *listener) {
173fcf3ce44SJohn Forte 	lock();
174fcf3ce44SJohn Forte 	try {
175fcf3ce44SJohn Forte 		typedef vector<AdapterDeviceEventListener *>::iterator Iter;
176fcf3ce44SJohn Forte 		for (Iter tmp = adapterDeviceEventListeners.begin();
177fcf3ce44SJohn Forte 		    tmp != adapterDeviceEventListeners.end(); tmp++) {
178fcf3ce44SJohn Forte 			if (*tmp == listener) {
179fcf3ce44SJohn Forte 				adapterDeviceEventListeners.erase(tmp);
180fcf3ce44SJohn Forte 				unlock();
181fcf3ce44SJohn Forte 				return;
182fcf3ce44SJohn Forte 			}
183fcf3ce44SJohn Forte 		}
184fcf3ce44SJohn Forte 		throw InvalidHandleException();
185fcf3ce44SJohn Forte 	} catch (...) {
186fcf3ce44SJohn Forte 		unlock();
187fcf3ce44SJohn Forte 		throw;
188fcf3ce44SJohn Forte 	}
189fcf3ce44SJohn Forte }
190fcf3ce44SJohn Forte 
removeListener(TargetEventListener * listener)191fcf3ce44SJohn Forte void FCSyseventBridge::removeListener(TargetEventListener *listener) {
192fcf3ce44SJohn Forte     lock();
193fcf3ce44SJohn Forte     try {
194fcf3ce44SJohn Forte 	typedef vector<TargetEventListener *>::iterator Iter;
195fcf3ce44SJohn Forte 	for (Iter tmp = targetEventListeners.begin();
196fcf3ce44SJohn Forte 		tmp != targetEventListeners.end(); tmp++) {
197fcf3ce44SJohn Forte 	    if (*tmp == listener) {
198fcf3ce44SJohn Forte 		targetEventListeners.erase(tmp);
199fcf3ce44SJohn Forte 		unlock();
200fcf3ce44SJohn Forte 		return;
201fcf3ce44SJohn Forte 	    }
202fcf3ce44SJohn Forte 	}
203fcf3ce44SJohn Forte 	throw InvalidHandleException();
204fcf3ce44SJohn Forte     } catch (...) {
205fcf3ce44SJohn Forte 	unlock();
206fcf3ce44SJohn Forte 	throw;
207fcf3ce44SJohn Forte     }
208fcf3ce44SJohn Forte }
209fcf3ce44SJohn Forte 
static_dispatch(sysevent_t * ev)210fcf3ce44SJohn Forte extern "C" void static_dispatch(sysevent_t *ev) {
211fcf3ce44SJohn Forte     Trace log("static_dispatch");
212fcf3ce44SJohn Forte     FCSyseventBridge::getInstance()->dispatch(ev);
213fcf3ce44SJohn Forte }
214fcf3ce44SJohn Forte 
dispatch(sysevent_t * ev)215fcf3ce44SJohn Forte void FCSyseventBridge::dispatch(sysevent_t *ev) {
216fcf3ce44SJohn Forte     Trace log("FCSyseventBridge::dispatch");
217fcf3ce44SJohn Forte     nvlist_t		    *list = NULL;
218fcf3ce44SJohn Forte     hrtime_t			when;
219fcf3ce44SJohn Forte 
220fcf3ce44SJohn Forte     if (ev == NULL) {
221fcf3ce44SJohn Forte 	log.debug("Null event.");
222fcf3ce44SJohn Forte 	return;
223fcf3ce44SJohn Forte     }
224fcf3ce44SJohn Forte 
225fcf3ce44SJohn Forte     if (sysevent_get_attr_list(ev, &list) || list == NULL) {
226fcf3ce44SJohn Forte 	log.debug("Empty event.");
227fcf3ce44SJohn Forte 	return;
228fcf3ce44SJohn Forte     }
229fcf3ce44SJohn Forte 
230fcf3ce44SJohn Forte     string eventVendor = sysevent_get_vendor_name(ev);
231fcf3ce44SJohn Forte     string eventPublisher = sysevent_get_pub_name(ev);
232fcf3ce44SJohn Forte     string eventClass = sysevent_get_class_name(ev);
233fcf3ce44SJohn Forte     string eventSubClass = sysevent_get_subclass_name(ev);
234fcf3ce44SJohn Forte 
235fcf3ce44SJohn Forte     sysevent_get_time(ev, &when);
236fcf3ce44SJohn Forte 
237fcf3ce44SJohn Forte     // Now that we know what type of event it is, handle it accordingly
238fcf3ce44SJohn Forte     if (eventClass == "EC_sunfc") {
239fcf3ce44SJohn Forte 
240fcf3ce44SJohn Forte 	// All events of this class type have instance and port-wwn for
241fcf3ce44SJohn Forte 	// the HBA port.
242fcf3ce44SJohn Forte 	uint32_t	instance;
243fcf3ce44SJohn Forte 	if (nvlist_lookup_uint32(list, (char *)"instance",
244fcf3ce44SJohn Forte 		&instance)) {
245fcf3ce44SJohn Forte 	    log.genericIOError(
246fcf3ce44SJohn Forte 		"Improperly formed event: no instance field.");
247fcf3ce44SJohn Forte 	    nvlist_free(list);
248fcf3ce44SJohn Forte 	    return;
249fcf3ce44SJohn Forte 	}
250fcf3ce44SJohn Forte 	uchar_t		*rawPortWWN;
251fcf3ce44SJohn Forte 	uint32_t	rawPortWWNLength;
252fcf3ce44SJohn Forte 
253fcf3ce44SJohn Forte 	if (nvlist_lookup_byte_array(list, (char *)"port-wwn",
254fcf3ce44SJohn Forte 		&rawPortWWN, &rawPortWWNLength)) {
255fcf3ce44SJohn Forte 	    log.genericIOError(
256fcf3ce44SJohn Forte 		"Improperly formed event: no port-wwn field.");
257fcf3ce44SJohn Forte 	    nvlist_free(list);
258fcf3ce44SJohn Forte 	    return;
259fcf3ce44SJohn Forte 	}
260fcf3ce44SJohn Forte 
261fcf3ce44SJohn Forte 	// Now deal with the specific details of each subclass type
262fcf3ce44SJohn Forte 	if (eventSubClass == "ESC_sunfc_port_offline") {
263fcf3ce44SJohn Forte 
264fcf3ce44SJohn Forte 	    // Create event instance
265fcf3ce44SJohn Forte 	    AdapterPortEvent event(
266fcf3ce44SJohn Forte 		wwnConversion(rawPortWWN),
267fcf3ce44SJohn Forte 		AdapterPortEvent::OFFLINE,
268fcf3ce44SJohn Forte 		0);
269fcf3ce44SJohn Forte 
270fcf3ce44SJohn Forte 	    // Dispatch to interested parties.
271fcf3ce44SJohn Forte 	    lock();
272fcf3ce44SJohn Forte 	    try {
273fcf3ce44SJohn Forte 		typedef vector<AdapterPortEventListener *>::iterator Iter;
274fcf3ce44SJohn Forte 		for (Iter tmp = adapterPortEventListeners.begin();
275fcf3ce44SJohn Forte 			tmp != adapterPortEventListeners.end(); tmp++) {
276fcf3ce44SJohn Forte 		    (*tmp)->dispatch(event);
277fcf3ce44SJohn Forte 		}
278fcf3ce44SJohn Forte 	    } catch (...) {
279fcf3ce44SJohn Forte 		unlock();
280fcf3ce44SJohn Forte 		nvlist_free(list);
281fcf3ce44SJohn Forte 		throw;
282fcf3ce44SJohn Forte 	    }
283fcf3ce44SJohn Forte 	    unlock();
284fcf3ce44SJohn Forte 
285fcf3ce44SJohn Forte 	} else if (eventSubClass == "ESC_sunfc_port_online") {
286fcf3ce44SJohn Forte 
287fcf3ce44SJohn Forte 	    // Create event instance
288fcf3ce44SJohn Forte 	    AdapterPortEvent event(
289fcf3ce44SJohn Forte 		wwnConversion(rawPortWWN),
290fcf3ce44SJohn Forte 		AdapterPortEvent::ONLINE,
291fcf3ce44SJohn Forte 		0);
292fcf3ce44SJohn Forte 
293fcf3ce44SJohn Forte 	    // Dispatch to interested parties.
294fcf3ce44SJohn Forte 	    lock();
295fcf3ce44SJohn Forte 	    try {
296fcf3ce44SJohn Forte 		typedef vector<AdapterPortEventListener *>::iterator Iter;
297fcf3ce44SJohn Forte 		for (Iter tmp = adapterPortEventListeners.begin();
298fcf3ce44SJohn Forte 			tmp != adapterPortEventListeners.end(); tmp++) {
299fcf3ce44SJohn Forte 		    (*tmp)->dispatch(event);
300fcf3ce44SJohn Forte 		}
301fcf3ce44SJohn Forte 	    } catch (...) {
302fcf3ce44SJohn Forte 		unlock();
303fcf3ce44SJohn Forte 		nvlist_free(list);
304fcf3ce44SJohn Forte 		throw;
305fcf3ce44SJohn Forte 	    }
306fcf3ce44SJohn Forte 	    unlock();
307fcf3ce44SJohn Forte 
308fcf3ce44SJohn Forte 	} else if (eventSubClass == "ESC_sunfc_device_online") {
309fcf3ce44SJohn Forte 		AdapterDeviceEvent event(
310fcf3ce44SJohn Forte 		    wwnConversion(rawPortWWN),
311fcf3ce44SJohn Forte 		    AdapterDeviceEvent::ONLINE,
312fcf3ce44SJohn Forte 		    0);
313fcf3ce44SJohn Forte 		lock();
314fcf3ce44SJohn Forte 		try {
315fcf3ce44SJohn Forte 			typedef vector<AdapterDeviceEventListener *>::iterator Iter;
316fcf3ce44SJohn Forte 			for (Iter tmp = adapterDeviceEventListeners.begin();
317fcf3ce44SJohn Forte 			    tmp != adapterDeviceEventListeners.end(); tmp++) {
318fcf3ce44SJohn Forte 				(*tmp)->dispatch(event);
319fcf3ce44SJohn Forte 			}
320fcf3ce44SJohn Forte 		} catch (...) {
321fcf3ce44SJohn Forte 			unlock();
322fcf3ce44SJohn Forte 			nvlist_free(list);
323fcf3ce44SJohn Forte 			throw;
324fcf3ce44SJohn Forte 		}
325fcf3ce44SJohn Forte 		unlock();
326fcf3ce44SJohn Forte 
327fcf3ce44SJohn Forte 	} else if (eventSubClass == "ESC_sunfc_device_offline") {
328fcf3ce44SJohn Forte 		AdapterDeviceEvent event(
329fcf3ce44SJohn Forte 		    wwnConversion(rawPortWWN),
330fcf3ce44SJohn Forte 		    AdapterDeviceEvent::OFFLINE,
331fcf3ce44SJohn Forte 		    0);
332fcf3ce44SJohn Forte 		lock();
333fcf3ce44SJohn Forte 		try {
334fcf3ce44SJohn Forte 			typedef vector<AdapterDeviceEventListener *>::iterator Iter;
335fcf3ce44SJohn Forte 			for (Iter tmp = adapterDeviceEventListeners.begin();
336fcf3ce44SJohn Forte 			    tmp != adapterDeviceEventListeners.end(); tmp++) {
337fcf3ce44SJohn Forte 				(*tmp)->dispatch(event);
338fcf3ce44SJohn Forte 			}
339fcf3ce44SJohn Forte 		} catch (...) {
340fcf3ce44SJohn Forte 			unlock();
341fcf3ce44SJohn Forte 			nvlist_free(list);
342fcf3ce44SJohn Forte 			throw;
343fcf3ce44SJohn Forte 		}
344fcf3ce44SJohn Forte 		unlock();
345fcf3ce44SJohn Forte 
346fcf3ce44SJohn Forte 	} else if (eventSubClass == "ESC_sunfc_port_rscn") {
347fcf3ce44SJohn Forte 	    /*
348fcf3ce44SJohn Forte 	     * RSCNs are a little tricky.  There can be multiple
349fcf3ce44SJohn Forte 	     * affected page properties, each numbered.  To make sure
350fcf3ce44SJohn Forte 	     * we get them all, we loop through all properties
351fcf3ce44SJohn Forte 	     * in the nvlist and if their name begins with "affected_page_"
352fcf3ce44SJohn Forte 	     * then we send an event for them.
353fcf3ce44SJohn Forte 	     */
354fcf3ce44SJohn Forte 	    uint32_t	affected_page;
355fcf3ce44SJohn Forte 	    nvpair_t    *attr = NULL;
356fcf3ce44SJohn Forte 	    for (attr = nvlist_next_nvpair(list, NULL);
357fcf3ce44SJohn Forte 		    attr != NULL;
358fcf3ce44SJohn Forte 		    attr = nvlist_next_nvpair(list, attr)) {
359fcf3ce44SJohn Forte 		string name = nvpair_name(attr);
360fcf3ce44SJohn Forte 		if (name.find("affected_page_") != name.npos) {
361fcf3ce44SJohn Forte 
362fcf3ce44SJohn Forte 		    if (nvpair_value_uint32(attr, &affected_page)) {
363fcf3ce44SJohn Forte 			log.genericIOError(
364fcf3ce44SJohn Forte 			    "Improperly formed event: "
365fcf3ce44SJohn Forte 			    "corrupt affected_page field");
366fcf3ce44SJohn Forte 			continue;
367fcf3ce44SJohn Forte 		    }
368fcf3ce44SJohn Forte 		    // Create event instance
369fcf3ce44SJohn Forte 		    AdapterPortEvent event(
370fcf3ce44SJohn Forte 			wwnConversion(rawPortWWN),
371fcf3ce44SJohn Forte 			AdapterPortEvent::FABRIC,
372fcf3ce44SJohn Forte 			affected_page);
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte 		    // Dispatch to interested parties.
375fcf3ce44SJohn Forte 		    lock();
376fcf3ce44SJohn Forte 		    typedef vector<AdapterPortEventListener *>::iterator Iter;
377fcf3ce44SJohn Forte 		    try {
378fcf3ce44SJohn Forte 			for (Iter tmp = adapterPortEventListeners.begin();
379fcf3ce44SJohn Forte 				tmp != adapterPortEventListeners.end(); tmp++) {
380fcf3ce44SJohn Forte 			    (*tmp)->dispatch(event);
381fcf3ce44SJohn Forte 			}
382fcf3ce44SJohn Forte 		    } catch (...) {
383fcf3ce44SJohn Forte 			unlock();
384fcf3ce44SJohn Forte 			nvlist_free(list);
385fcf3ce44SJohn Forte 			throw;
386fcf3ce44SJohn Forte 		    }
387fcf3ce44SJohn Forte 		    unlock();
388fcf3ce44SJohn Forte 		}
389fcf3ce44SJohn Forte 	    }
390fcf3ce44SJohn Forte 	} else if (eventSubClass == "ESC_sunfc_target_add") {
391fcf3ce44SJohn Forte 	    uchar_t	*rawTargetPortWWN;
392fcf3ce44SJohn Forte 	    uint32_t	rawTargetPortWWNLength;
393fcf3ce44SJohn Forte 
394fcf3ce44SJohn Forte 	    if (nvlist_lookup_byte_array(list, (char *)"target-port-wwn",
395fcf3ce44SJohn Forte 		    &rawTargetPortWWN, &rawTargetPortWWNLength)) {
396fcf3ce44SJohn Forte 		log.genericIOError(
397fcf3ce44SJohn Forte 		    "Improperly formed event: no target-port-wwn field.");
398fcf3ce44SJohn Forte 		nvlist_free(list);
399fcf3ce44SJohn Forte 		return;
400fcf3ce44SJohn Forte 	    }
401fcf3ce44SJohn Forte 
402fcf3ce44SJohn Forte 	    // Create event instance
403fcf3ce44SJohn Forte 	    AdapterPortEvent event(
404fcf3ce44SJohn Forte 		wwnConversion(rawPortWWN),
405fcf3ce44SJohn Forte 		AdapterPortEvent::NEW_TARGETS,
406fcf3ce44SJohn Forte 		0);
407fcf3ce44SJohn Forte 
408fcf3ce44SJohn Forte 	    // Dispatch to interested parties.
409fcf3ce44SJohn Forte 	    lock();
410fcf3ce44SJohn Forte 	    try {
411fcf3ce44SJohn Forte 		typedef vector<AdapterPortEventListener *>::iterator Iter;
412fcf3ce44SJohn Forte 		for (Iter tmp = adapterPortEventListeners.begin();
413fcf3ce44SJohn Forte 			tmp != adapterPortEventListeners.end(); tmp++) {
414fcf3ce44SJohn Forte 		    (*tmp)->dispatch(event);
415fcf3ce44SJohn Forte 		}
416fcf3ce44SJohn Forte 	    } catch (...) {
417fcf3ce44SJohn Forte 		unlock();
418fcf3ce44SJohn Forte 		nvlist_free(list);
419fcf3ce44SJohn Forte 		throw;
420fcf3ce44SJohn Forte 	    }
421fcf3ce44SJohn Forte 	    unlock();
422fcf3ce44SJohn Forte 	} else if (eventSubClass == "ESC_sunfc_target_remove") {
423fcf3ce44SJohn Forte 	    uchar_t	*rawTargetPortWWN;
424fcf3ce44SJohn Forte 	    uint32_t	rawTargetPortWWNLength;
425fcf3ce44SJohn Forte 
426fcf3ce44SJohn Forte 	    if (nvlist_lookup_byte_array(list, (char *)"target-port-wwn",
427fcf3ce44SJohn Forte 		    &rawTargetPortWWN, &rawTargetPortWWNLength)) {
428fcf3ce44SJohn Forte 		log.genericIOError(
429fcf3ce44SJohn Forte 		    "Improperly formed event: no target-port-wwn field.");
430fcf3ce44SJohn Forte 		nvlist_free(list);
431fcf3ce44SJohn Forte 		return;
432fcf3ce44SJohn Forte 	    }
433fcf3ce44SJohn Forte 	    // Create event instance
434fcf3ce44SJohn Forte 	    TargetEvent event(
435fcf3ce44SJohn Forte 		wwnConversion(rawPortWWN),
436fcf3ce44SJohn Forte 		wwnConversion(rawTargetPortWWN),
437fcf3ce44SJohn Forte 		TargetEvent::REMOVED);
438fcf3ce44SJohn Forte 
439fcf3ce44SJohn Forte 	    // Dispatch to interested parties.
440fcf3ce44SJohn Forte 	    lock();
441fcf3ce44SJohn Forte 	    try {
442fcf3ce44SJohn Forte 		typedef vector<TargetEventListener *>::iterator Iter;
443fcf3ce44SJohn Forte 		for (Iter tmp = targetEventListeners.begin();
444fcf3ce44SJohn Forte 			tmp != targetEventListeners.end(); tmp++) {
445fcf3ce44SJohn Forte 		    (*tmp)->dispatch(event);
446fcf3ce44SJohn Forte 		}
447fcf3ce44SJohn Forte 	    } catch (...) {
448fcf3ce44SJohn Forte 		unlock();
449fcf3ce44SJohn Forte 		nvlist_free(list);
450fcf3ce44SJohn Forte 		throw;
451fcf3ce44SJohn Forte 	    }
452fcf3ce44SJohn Forte 	    unlock();
453fcf3ce44SJohn Forte 	} else if (eventSubClass == "ESC_sunfc_port_attach") {
454fcf3ce44SJohn Forte 	    // Create event instance
455fcf3ce44SJohn Forte 	    AdapterAddEvent event(wwnConversion(rawPortWWN));
456fcf3ce44SJohn Forte 	    // Dispatch to interested parties.
457fcf3ce44SJohn Forte 	    lock();
458fcf3ce44SJohn Forte 	    try {
459fcf3ce44SJohn Forte 		typedef vector<AdapterAddEventListener *>::iterator Iter;
460fcf3ce44SJohn Forte 		for (Iter tmp = adapterAddEventListeners.begin();
461fcf3ce44SJohn Forte 			tmp != adapterAddEventListeners.end(); tmp++) {
462fcf3ce44SJohn Forte 		    (*tmp)->dispatch(event);
463fcf3ce44SJohn Forte 		}
464fcf3ce44SJohn Forte 	    } catch (...) {
465fcf3ce44SJohn Forte 		unlock();
466fcf3ce44SJohn Forte 		nvlist_free(list);
467fcf3ce44SJohn Forte 		throw;
468fcf3ce44SJohn Forte 	    }
469fcf3ce44SJohn Forte 	    unlock();
470fcf3ce44SJohn Forte 	} else if (eventSubClass == "ESC_sunfc_port_detach") {
471fcf3ce44SJohn Forte 	    // Technically, we should probably try to coalesce
472fcf3ce44SJohn Forte 	    // all detach events for the same multi-ported adapter
473fcf3ce44SJohn Forte 	    // and only send one event to the client, but for now,
474fcf3ce44SJohn Forte 	    // we'll just blindly send duplicates.
475fcf3ce44SJohn Forte 
476fcf3ce44SJohn Forte 	    // Create event instance
477fcf3ce44SJohn Forte 	    AdapterEvent event(
478fcf3ce44SJohn Forte 		wwnConversion(rawPortWWN),
479fcf3ce44SJohn Forte 		AdapterEvent::REMOVE);
480fcf3ce44SJohn Forte 
481fcf3ce44SJohn Forte 	    // Dispatch to interested parties.
482fcf3ce44SJohn Forte 	    lock();
483fcf3ce44SJohn Forte 	    try {
484fcf3ce44SJohn Forte 		typedef vector<AdapterEventListener *>::iterator Iter;
485fcf3ce44SJohn Forte 		for (Iter tmp = adapterEventListeners.begin();
486fcf3ce44SJohn Forte 			tmp != adapterEventListeners.end(); tmp++) {
487fcf3ce44SJohn Forte 		    (*tmp)->dispatch(event);
488fcf3ce44SJohn Forte 		}
489fcf3ce44SJohn Forte 	    } catch (...) {
490fcf3ce44SJohn Forte 		unlock();
491fcf3ce44SJohn Forte 		nvlist_free(list);
492fcf3ce44SJohn Forte 		throw;
493fcf3ce44SJohn Forte 	    }
494fcf3ce44SJohn Forte 	    unlock();
495fcf3ce44SJohn Forte 
496fcf3ce44SJohn Forte 	} else {
497fcf3ce44SJohn Forte 	    log.genericIOError(
498fcf3ce44SJohn Forte 		    "Unrecognized subclass \"%s\": Ignoring event",
499fcf3ce44SJohn Forte 		    eventSubClass.c_str());
500fcf3ce44SJohn Forte 	}
501fcf3ce44SJohn Forte     } else {
502fcf3ce44SJohn Forte 	// This should not happen, as we only asked for specific classes.
503fcf3ce44SJohn Forte 	log.genericIOError(
504fcf3ce44SJohn Forte 		"Unrecognized class \"%s\": Ignoring event",
505fcf3ce44SJohn Forte 		eventClass.c_str());
506fcf3ce44SJohn Forte     }
507fcf3ce44SJohn Forte     nvlist_free(list);
508fcf3ce44SJohn Forte }
509fcf3ce44SJohn Forte 
validateRegistration()510fcf3ce44SJohn Forte void FCSyseventBridge::validateRegistration() {
511fcf3ce44SJohn Forte     Trace log("FCSyseventBridge::validateRegistration");
512fcf3ce44SJohn Forte     uint64_t count = 0;
513fcf3ce44SJohn Forte     count = adapterAddEventListeners.size() +
514fcf3ce44SJohn Forte 	    adapterEventListeners.size() +
515fcf3ce44SJohn Forte 	    adapterPortEventListeners.size() +
516fcf3ce44SJohn Forte 	    targetEventListeners.size();
517fcf3ce44SJohn Forte     if (count == 1) {
518fcf3ce44SJohn Forte 	handle = sysevent_bind_handle(static_dispatch);
519fcf3ce44SJohn Forte 	if (handle == NULL) {
520fcf3ce44SJohn Forte 	    log.genericIOError(
521fcf3ce44SJohn Forte 		"Unable to bind sysevent handle.");
522fcf3ce44SJohn Forte 	    return;
523fcf3ce44SJohn Forte 	}
524fcf3ce44SJohn Forte 	const char *subclass_list[9] = {
525fcf3ce44SJohn Forte 		"ESC_sunfc_port_attach",
526fcf3ce44SJohn Forte 		"ESC_sunfc_port_detach",
527fcf3ce44SJohn Forte 		"ESC_sunfc_port_offline",
528fcf3ce44SJohn Forte 		"ESC_sunfc_port_online",
529fcf3ce44SJohn Forte 		"ESC_sunfc_port_rscn",
530fcf3ce44SJohn Forte 		"ESC_sunfc_target_add",
531fcf3ce44SJohn Forte 		"ESC_sunfc_target_remove",
532fcf3ce44SJohn Forte 		"ESC_sunfc_device_online",
533fcf3ce44SJohn Forte 		"ESC_sunfc_device_offline"
534fcf3ce44SJohn Forte 	    };
535fcf3ce44SJohn Forte 	if (sysevent_subscribe_event(handle,
536fcf3ce44SJohn Forte 		"EC_sunfc", (const char **)subclass_list, 9)) {
537fcf3ce44SJohn Forte 	    log.genericIOError(
538fcf3ce44SJohn Forte 		"Unable to subscribe to sun_fc events.");
539fcf3ce44SJohn Forte 	    sysevent_unbind_handle(handle);
540fcf3ce44SJohn Forte 	    handle = NULL;
541fcf3ce44SJohn Forte 	}
542fcf3ce44SJohn Forte     } else if (count == 0 && handle != NULL) {
543fcf3ce44SJohn Forte 	// Remove subscription
544fcf3ce44SJohn Forte 	sysevent_unbind_handle(handle);
545fcf3ce44SJohn Forte 	handle == NULL;
546fcf3ce44SJohn Forte     } // Else do nothing
547fcf3ce44SJohn Forte }
548fcf3ce44SJohn Forte 
getMaxListener()549fcf3ce44SJohn Forte int32_t FCSyseventBridge::getMaxListener() {
550fcf3ce44SJohn Forte     return (INT_MAX);
551fcf3ce44SJohn Forte }
552