1 /*        $NetBSD: if_dse.c,v 1.8 2024/09/08 04:42:49 nat Exp $ */
2 
3 /*
4  * Driver for DaynaPORT SCSI/Link SCSI-Ethernet
5  *
6  * Written by Hiroshi Noguchi <ngc@ff.iij4u.or.jp>
7  *
8  * Modified by Matt Sandstrom <mattias@beauty.se> for NetBSD 1.5.3
9  *
10  * This driver is written based on "if_se.c".
11  */
12 
13 /*
14  * Copyright (c) 1997 Ian W. Dall <ian.dall@dsto.defence.gov.au>
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. All advertising materials mentioning features or use of this software
26  *    must display the following acknowledgement:
27  *        This product includes software developed by Ian W. Dall.
28  * 4. The name of the author may not be used to endorse or promote products
29  *    derived from this software without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  */
42 
43 #include "opt_inet.h"
44 #include "opt_atalk.h"
45 
46 #include <sys/types.h>
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/callout.h>
50 #include <sys/syslog.h>
51 #include <sys/kernel.h>
52 #include <sys/file.h>
53 #include <sys/stat.h>
54 #include <sys/ioctl.h>
55 #include <sys/buf.h>
56 #include <sys/uio.h>
57 #include <sys/malloc.h>
58 #include <sys/errno.h>
59 #include <sys/device.h>
60 #include <sys/disklabel.h>
61 #include <sys/disk.h>
62 #include <sys/proc.h>
63 #include <sys/conf.h>
64 
65 #include <sys/workqueue.h>
66 
67 #include <dev/scsipi/scsipi_all.h>
68 #include <dev/scsipi/scsiconf.h>
69 
70 #include <sys/mbuf.h>
71 
72 #include <sys/socket.h>
73 #include <net/if.h>
74 #include <net/if_dl.h>
75 #include <net/if_ether.h>
76 #include <net/if_media.h>
77 
78 #ifdef INET
79 #include <netinet/in.h>
80 #include <netinet/if_inarp.h>
81 #endif
82 
83 #ifdef NETATALK
84 #include <netatalk/at.h>
85 #endif
86 
87 #include <net/bpf.h>
88 
89 
90 /*
91  * debug flag
92  */
93 #if 0
94 #define   DSE_DEBUG
95 #endif
96 
97 
98 #define DSE_TIMEOUT 100000
99 #define   DSE_OUTSTANDING     4
100 #define   DSE_RETRIES         4
101 #define DSE_MINSIZE 60
102 
103 #define   DSE_HEADER_TX       4
104 #define   DSE_TAIL_TX         4
105 #define DSE_EXTRAS_TX         (DSE_HEADER_TX + DSE_TAIL_TX)
106 
107 #define   DSE_HEADER_RX       6
108 #define   DSE_TAIL_RX         0
109 #define   DSE_EXTRAS_RX       (DSE_HEADER_RX + DSE_TAIL_RX)
110 
111 #define   MAX_BYTES_RX        (ETHERMTU + sizeof(struct ether_header) + ETHER_CRC_LEN)
112 
113 /* 10 full length packets appears to be the max ever returned. 16k is OK */
114 #define RBUF_LEN    (16 * 1024)
115 
116 /*
117  * Tuning parameters:
118  *   We will attempt to adapt to polling fast enough to get RDATA_GOAL packets
119  *   per read
120  */
121 #define RDATA_MAX   10        /* maximum of returned packets (guessed) */
122 #define RDATA_GOAL  8
123 
124 /*
125  * maximum of available multicast address entries (guessed)
126  */
127 #define   DSE_MCAST_MAX       10
128 
129 
130 /* dse_poll and dse_poll0 are the normal polling rate and the minimum
131  * polling rate respectively. dse_poll0 should be chosen so that at
132  * maximum ethernet speed, we will read nearly RDATA_MAX packets. dse_poll
133  * should be chosen for reasonable maximum latency.
134  * In practice, if we are being saturated with min length packets, we
135  * can't poll fast enough. Polling with zero delay actually
136  * worsens performance. dse_poll0 is enforced to be always at least 1
137  */
138 #if MAC68K_DEBUG
139 #define DSE_POLL              50        /* default in milliseconds */
140 #define DSE_POLL0             30        /* default in milliseconds */
141 #else
142 #define DSE_POLL              80        /* default in milliseconds */
143 #define DSE_POLL0             40        /* default in milliseconds */
144 #endif
145 int dse_poll = 0;             /* Delay in ticks set at attach time */
146 int dse_poll0 = 0;
147 int dse_max_received = 0;     /* Instrumentation */
148 
149 
150 
151 
152 /*==========================================
153   data type defs
154 ==========================================*/
155 typedef struct scsipi_inquiry_data dayna_ether_inquiry_data;
156 
157 typedef struct {
158           uint8_t   opcode[2];
159           uint8_t   byte3;
160           uint8_t   length[2];
161           uint8_t   byte6;
162 } scsi_dayna_ether_generic;
163 
164 #define   DAYNA_CMD_SEND                0x0A                /* same as generic "Write" */
165 #define   DAYNA_CMD_RECV                0x08                /* same as generic "Read" */
166 
167 #define   DAYNA_CMD_GET_ADDR  0x09                /* ???: read MAC address ? */
168 #define   REQ_LEN_GET_ADDR    0x12
169 
170 #define   DAYNA_CMD_SET_MULTI 0x0D                /* set multicast address */
171 
172 #define   DAYNA_CMD_VENDOR1   0x0E                /* ???: initialize signal ? */
173 
174 #define IS_SEND(generic)      ((generic)->opcode == DAYNA_CMD_SEND)
175 #define IS_RECV(generic)      ((generic)->opcode == DAYNA_CMD_RECV)
176 
177 struct dse_softc {
178           device_t sc_dev;
179           struct    ethercom sc_ethercom;         /* Ethernet common part */
180           struct scsipi_periph *sc_periph;/* contains our targ, lun, etc. */
181 
182           struct callout sc_recv_ch;
183           struct kmutex sc_iflock;
184           struct if_percpuq *sc_ipq;
185           struct workqueue *sc_recv_wq, *sc_send_wq;
186           struct work sc_recv_work, sc_send_work;
187           int sc_recv_work_pending, sc_send_work_pending;
188 
189           char *sc_tbuf;
190           char *sc_rbuf;
191           int sc_debug;
192           int sc_flags;
193           int sc_last_timeout;
194           int sc_enabled;
195           int sc_attach_state;
196 };
197 
198 /* bit defs of "sc_flags" */
199 #define DSE_NEED_RECV         0x1
200 
201 static int          dsematch(device_t, cfdata_t, void *);
202 static void         dseattach(device_t, device_t, void *);
203 static int          dsedetach(device_t, int);
204 
205 static void         dse_ifstart(struct ifnet *);
206 static void         dse_send_worker(struct work *wk, void *cookie);
207 
208 static void         dsedone(struct scsipi_xfer *, int);
209 static int          dse_ioctl(struct ifnet *, u_long, void *);
210 static void         dsewatchdog(struct ifnet *);
211 
212 static void         dse_recv_callout(void *);
213 static void         dse_recv_worker(struct work *wk, void *cookie);
214 static void         dse_recv(struct dse_softc *);
215 static struct mbuf* dse_get(struct dse_softc *, uint8_t *, int);
216 static int          dse_read(struct dse_softc *, uint8_t *, int);
217 
218 static int          dse_init_adaptor(struct dse_softc *);
219 static int          dse_get_addr(struct dse_softc *, uint8_t *);
220 static int          dse_set_multi(struct dse_softc *);
221 
222 static int          dse_reset(struct dse_softc *);
223 
224 #if 0     /* 07/16/2000 comment-out */
225 static int          dse_set_mode(struct dse_softc *, int, int);
226 #endif
227 static int          dse_init(struct dse_softc *);
228 static void         dse_stop(struct dse_softc *);
229 
230 #if 0
231 static __inline uint16_t      ether_cmp(void *, void *);
232 #endif
233 
234 static inline int dse_scsipi_cmd(struct scsipi_periph *periph,
235                               struct scsipi_generic *scsipi_cmd,
236                               int cmdlen, u_char *data_addr, int datalen,
237                               int retries, int timeout, struct buf *bp,
238                               int flags);
239 
240 int       dse_enable(struct dse_softc *);
241 void      dse_disable(struct dse_softc *);
242 
243 
244 CFATTACH_DECL_NEW(dse, sizeof(struct dse_softc),
245     dsematch, dseattach, dsedetach, NULL);
246 
247 extern struct cfdriver dse_cd;
248 
249 dev_type_open(dseopen);
250 dev_type_close(dseclose);
251 dev_type_ioctl(dseioctl);
252 
253 const struct cdevsw dse_cdevsw = {
254           .d_open = dseopen,
255           .d_close = dseclose,
256           .d_read = noread,
257           .d_write = nowrite,
258           .d_ioctl = dseioctl,
259           .d_stop = nostop,
260           .d_tty = notty,
261           .d_poll = nopoll,
262           .d_mmap = nommap,
263           .d_kqfilter = nokqfilter,
264           .d_discard = nodiscard,
265           .d_flag = D_OTHER | D_MPSAFE
266 };
267 
268 const struct scsipi_periphsw dse_switch = {
269 
270           NULL,                         /* Use default error handler */
271           NULL,               /* have no queue */
272           NULL,                         /* have no async handler */
273           dsedone,            /* deal with stats at interrupt time */
274 };
275 
276 struct scsipi_inquiry_pattern dse_patterns[] = {
277           {         T_PROCESSOR,        T_FIXED,
278                     "Dayna",            "SCSI/Link",                  "" },
279 };
280 
281 
282 
283 /*====================================================
284   definitions for SCSI commands
285 ====================================================*/
286 
287 /*
288  * command templates
289  */
290 /* unknown commands */
291 /* Vendor #1 */
292 static const scsi_dayna_ether_generic   sonic_ether_vendor1 = {
293           { DAYNA_CMD_VENDOR1, 0x00 },
294           0x00,
295           { 0x00, 0x00 },
296           0x80
297 };
298 
299 
300 
301 #if 0
302 /*
303  * Compare two Ether/802 addresses for equality, inlined and
304  * unrolled for speed.
305  * Note: use this like memcmp()
306  */
307 static __inline uint16_t
308 ether_cmp(void *one, void *two)
309 {
310           uint16_t* a;
311           uint16_t* b;
312           uint16_t diff;
313 
314           a = (uint16_t *) one;
315           b = (uint16_t *) two;
316 
317           diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]);
318 
319           return (diff);
320 }
321 
322 #define ETHER_CMP   ether_cmp
323 #endif
324 
325 /*
326  * check to match with SCSI inquiry information
327  */
328 static int
dsematch(device_t parent,cfdata_t match,void * aux)329 dsematch(device_t parent, cfdata_t match, void *aux)
330 {
331           struct scsipibus_attach_args *sa = aux;
332           int priority;
333 
334           (void)scsipi_inqmatch(&sa->sa_inqbuf,
335               dse_patterns, sizeof(dse_patterns) / sizeof(dse_patterns[0]),
336               sizeof(dse_patterns[0]), &priority);
337           return priority;
338 }
339 
340 
341 /*
342  * The routine called by the low level scsi routine when it discovers
343  * a device suitable for this driver.
344  */
345 static void
dseattach(device_t parent,device_t self,void * aux)346 dseattach(device_t parent, device_t self, void *aux)
347 {
348           struct dse_softc *sc = device_private(self);
349           struct scsipibus_attach_args *sa = aux;
350           struct scsipi_periph *periph = sa->sa_periph;
351           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
352           uint8_t myaddr[ETHER_ADDR_LEN];
353           char wqname[MAXCOMLEN];
354           int rv;
355 
356           sc->sc_dev = self;
357 
358           aprint_normal("\n");
359           SC_DEBUG(periph, SCSIPI_DB2, ("dseattach: "));
360 
361           sc->sc_attach_state = 0;
362           callout_init(&sc->sc_recv_ch, CALLOUT_MPSAFE);
363           callout_setfunc(&sc->sc_recv_ch, dse_recv_callout, (void *)sc);
364           mutex_init(&sc->sc_iflock, MUTEX_DEFAULT, IPL_SOFTNET);
365 
366           /*
367            * Store information needed to contact our base driver
368            */
369           sc->sc_periph = periph;
370           periph->periph_dev = sc->sc_dev;
371           periph->periph_switch = &dse_switch;
372 #if 0
373           sc_periph->sc_link_dbflags = SCSIPI_DB1;
374 #endif
375 
376           dse_poll = mstohz(DSE_POLL);
377           dse_poll = dse_poll? dse_poll: 1;
378           dse_poll0 = mstohz(DSE_POLL0);
379           dse_poll0 = dse_poll0? dse_poll0: 1;
380 
381           /*
382            * Initialize and attach send and receive buffers
383            */
384           sc->sc_tbuf = malloc(ETHERMTU + sizeof(struct ether_header) +
385               DSE_EXTRAS_TX + 16, M_DEVBUF, M_WAITOK);
386 
387           sc->sc_rbuf = malloc(RBUF_LEN + 16, M_DEVBUF, M_WAITOK);
388 
389           /* initialize adaptor and obtain MAC address */
390           dse_init_adaptor(sc);
391           sc->sc_attach_state = 1;
392 
393           /* Initialize ifnet structure. */
394           strcpy(ifp->if_xname, device_xname(sc->sc_dev));
395           ifp->if_softc = sc;
396           ifp->if_start = dse_ifstart;
397           ifp->if_ioctl = dse_ioctl;
398           ifp->if_watchdog = dsewatchdog;
399           ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
400           ifp->if_extflags = IFEF_MPSAFE;
401 
402           dse_get_addr(sc, myaddr);
403 
404           /* Attach the interface. */
405           if_initialize(ifp);
406 
407           snprintf(wqname, sizeof(wqname), "%sRx", device_xname(sc->sc_dev));
408           rv = workqueue_create(&sc->sc_recv_wq, wqname, dse_recv_worker, sc,
409               PRI_SOFTNET, IPL_NET, WQ_MPSAFE);
410           if (rv != 0) {
411                     aprint_error_dev(sc->sc_dev,
412                         "unable to create recv Rx workqueue\n");
413                     dsedetach(sc->sc_dev, 0);
414                     return; /* Error */
415           }
416           sc->sc_recv_work_pending = false;
417           sc->sc_attach_state = 2;
418 
419           snprintf(wqname, sizeof(wqname), "%sTx", device_xname(sc->sc_dev));
420           rv = workqueue_create(&sc->sc_send_wq, wqname, dse_send_worker, ifp,
421               PRI_SOFTNET, IPL_NET, WQ_MPSAFE);
422           if (rv != 0) {
423                     aprint_error_dev(sc->sc_dev,
424                         "unable to create send Tx workqueue\n");
425                     dsedetach(sc->sc_dev, 0);
426                     return; /* Error */
427           }
428           sc->sc_send_work_pending = false;
429           sc->sc_ipq = if_percpuq_create(&sc->sc_ethercom.ec_if);
430           ether_ifattach(ifp, myaddr);
431           if_register(ifp);
432           sc->sc_attach_state = 4;
433 
434           bpf_attach(ifp, DLT_EN10MB, sizeof(struct ether_header));
435 }
436 
437 static int
dsedetach(device_t self,int flags)438 dsedetach(device_t self, int flags)
439 {
440           struct dse_softc *sc = device_private(self);
441           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
442 
443           switch(sc->sc_attach_state) {
444           case 4:
445                     dse_stop(sc);
446                     mutex_enter(&sc->sc_iflock);
447                     ifp->if_flags &= ~IFF_RUNNING;
448                     dse_disable(sc);
449                     ether_ifdetach(ifp);
450                     if_detach(ifp);
451                     mutex_exit(&sc->sc_iflock);
452                     if_percpuq_destroy(sc->sc_ipq);
453                     /*FALLTHROUGH*/
454           case 3:
455                     workqueue_destroy(sc->sc_send_wq);
456                     /*FALLTHROUGH*/
457           case 2:
458                     workqueue_destroy(sc->sc_recv_wq);
459                     /*FALLTHROUGH*/
460           case 1:
461                     free(sc->sc_rbuf, M_DEVBUF);
462                     free(sc->sc_tbuf, M_DEVBUF);
463                     callout_destroy(&sc->sc_recv_ch);
464                     mutex_destroy(&sc->sc_iflock);
465                     break;
466           default:
467                     aprint_error_dev(sc->sc_dev, "detach failed (state %d)\n",
468                         sc->sc_attach_state);
469                     return 1;
470                     break;
471           }
472 
473           return 0;
474 }
475 
476 
477 /*
478  * submit SCSI command
479  */
480 static __inline int
dse_scsipi_cmd(struct scsipi_periph * periph,struct scsipi_generic * cmd,int cmdlen,u_char * data_addr,int datalen,int retries,int timeout,struct buf * bp,int flags)481 dse_scsipi_cmd(struct scsipi_periph *periph, struct scsipi_generic *cmd,
482     int cmdlen, u_char *data_addr, int datalen, int retries, int timeout,
483     struct buf *bp, int flags)
484 {
485           int error = 0;
486 
487           error = scsipi_command(periph, cmd, cmdlen, data_addr,
488                      datalen, retries, timeout, bp, flags);
489 
490           return error;
491 }
492 
493 
494 /*
495  * Start routine for calling from network sub system
496  */
497 static void
dse_ifstart(struct ifnet * ifp)498 dse_ifstart(struct ifnet *ifp)
499 {
500           struct dse_softc *sc = ifp->if_softc;
501 
502           mutex_enter(&sc->sc_iflock);
503           if (!sc->sc_send_work_pending)  {
504                     sc->sc_send_work_pending = true;
505                     workqueue_enqueue(sc->sc_send_wq, &sc->sc_send_work, NULL);
506           }
507           mutex_exit(&sc->sc_iflock);
508           if (sc->sc_flags & DSE_NEED_RECV) {
509                     sc->sc_flags &= ~DSE_NEED_RECV;
510           }
511 }
512 
513 /*
514  * Invoke the transmit workqueue and transmission on the interface.
515  */
516 static void
dse_send_worker(struct work * wk,void * cookie)517 dse_send_worker(struct work *wk, void *cookie)
518 {
519           struct ifnet *ifp = cookie;
520           struct dse_softc *sc = ifp->if_softc;
521           scsi_dayna_ether_generic cmd_send;
522           struct mbuf *m, *m0;
523           int len, error;
524           u_char *cp;
525 
526           mutex_enter(&sc->sc_iflock);
527           sc->sc_send_work_pending = false;
528           mutex_exit(&sc->sc_iflock);
529 
530           KASSERT(if_is_mpsafe(ifp));
531 
532           /* Don't transmit if interface is busy or not running */
533           if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
534                     return;
535 
536           while (1) {
537                     IFQ_DEQUEUE(&ifp->if_snd, m0);
538                     if (m0 == NULL)
539                               break;
540                     /* If BPF is listening on this interface, let it see the
541                      * packet before we commit it to the wire.
542                      */
543                     bpf_mtap(ifp, m0, BPF_D_OUT);
544 
545                     /* We need to use m->m_pkthdr.len, so require the header */
546                     if ((m0->m_flags & M_PKTHDR) == 0)
547                               panic("ctscstart: no header mbuf");
548                     len = m0->m_pkthdr.len;
549 
550                     /* Mark the interface busy. */
551                     ifp->if_flags |= IFF_OACTIVE;
552 
553                     /* Chain; copy into linear buffer allocated at attach time. */
554                     cp = sc->sc_tbuf;
555                     for (m = m0; m != NULL; ) {
556                               memcpy(cp, mtod(m, u_char *), m->m_len);
557                               cp += m->m_len;
558                               m = m0 = m_free(m);
559                     }
560                     if (len < DSE_MINSIZE) {
561 #ifdef DSE_DEBUG
562                               if (sc->sc_debug)
563                                         aprint_error_dev(sc->sc_dev,
564                                             "packet size %d (%zu) < %d\n", len,
565                                             cp - (u_char *)sc->sc_tbuf, DSE_MINSIZE);
566 #endif
567                               memset(cp, 0, DSE_MINSIZE - len);
568                               len = DSE_MINSIZE;
569                     }
570 
571                     /* Fill out SCSI command. */
572                     memset(&cmd_send, 0, sizeof(cmd_send));
573                     cmd_send.opcode[0] = DAYNA_CMD_SEND;
574                     _lto2b(len, &(cmd_send.length[0]));
575                     cmd_send.byte6 = 0x00;
576 
577                     /* Send command to device. */
578                     error = dse_scsipi_cmd(sc->sc_periph,
579                         (void *)&cmd_send, sizeof(cmd_send),
580                         sc->sc_tbuf, len, DSE_RETRIES,
581                         DSE_TIMEOUT, NULL, XS_CTL_NOSLEEP | XS_CTL_DATA_OUT);
582                     if (error) {
583                               aprint_error_dev(sc->sc_dev,
584                                   "not queued, error %d\n", error);
585                               if_statinc(ifp, if_oerrors);
586                               ifp->if_flags &= ~IFF_OACTIVE;
587                     } else
588                               if_statinc(ifp, if_opackets);
589           }
590 }
591 
592 
593 /*
594  * Called from the scsibus layer via our scsi device switch.
595  */
596 static void
dsedone(struct scsipi_xfer * xs,int error)597 dsedone(struct scsipi_xfer *xs, int error)
598 {
599           struct dse_softc *sc = device_private(xs->xs_periph->periph_dev);
600           struct scsipi_generic *cmd = xs->cmd;
601           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
602 
603           if (IS_SEND(cmd)) {
604                     ifp->if_flags &= ~IFF_OACTIVE;
605           } else if (IS_RECV(cmd)) {
606                     /* RECV complete */
607                     /* pass data up. reschedule a recv */
608                     /* scsipi_free_xs will call start. Harmless. */
609 
610                     if (error) {
611                               /* Reschedule after a delay */
612                               callout_schedule(&sc->sc_recv_ch, dse_poll);
613                     } else {
614                               int n, ntimeo;
615                               n = dse_read(sc, xs->data, xs->datalen - xs->resid);
616                               if (n > dse_max_received)
617                                         dse_max_received = n;
618                               if (n == 0)
619                                         ntimeo = dse_poll;
620                               else if (n >= RDATA_MAX)
621                                         ntimeo = dse_poll0;
622                               else {
623                                         ntimeo = sc->sc_last_timeout;
624                                         ntimeo = (ntimeo * RDATA_GOAL)/n;
625                                         ntimeo = (ntimeo < dse_poll0?
626                                                     dse_poll0: ntimeo);
627                                         ntimeo = (ntimeo > dse_poll?
628                                                     dse_poll: ntimeo);
629                               }
630                               sc->sc_last_timeout = ntimeo;
631                               callout_schedule(&sc->sc_recv_ch, ntimeo);
632                     }
633           }
634 }
635 
636 
637 /*
638  * Setup a receive command by queuing the work.
639  * Usually called from a callout, but also from se_init().
640  */
641 static void
dse_recv_callout(void * v)642 dse_recv_callout(void *v)
643 {
644           /* do a recv command */
645           struct dse_softc *sc = (struct dse_softc *) v;
646 
647           if (sc->sc_enabled == 0)
648                     return;
649 
650           mutex_enter(&sc->sc_iflock);
651           if (sc->sc_recv_work_pending == true) {
652                     callout_schedule(&sc->sc_recv_ch, dse_poll);
653                     mutex_exit(&sc->sc_iflock);
654                     return;
655           }
656 
657           sc->sc_recv_work_pending = true;
658           workqueue_enqueue(sc->sc_recv_wq, &sc->sc_recv_work, NULL);
659           mutex_exit(&sc->sc_iflock);
660 }
661 
662 /*
663  * Invoke the receive workqueue
664  */
665 static void
dse_recv_worker(struct work * wk,void * cookie)666 dse_recv_worker(struct work *wk, void *cookie)
667 {
668           struct dse_softc *sc = (struct dse_softc *) cookie;
669 
670           dse_recv(sc);
671           mutex_enter(&sc->sc_iflock);
672           sc->sc_recv_work_pending = false;
673           mutex_exit(&sc->sc_iflock);
674 
675 }
676 
677 /*
678  * Do the actual work of receiving data.
679  */
680 static void
dse_recv(struct dse_softc * sc)681 dse_recv(struct dse_softc *sc)
682 {
683           scsi_dayna_ether_generic cmd_recv;
684           int error, len;
685 
686           /* do a recv command */
687           /* fill out command buffer */
688           memset(&cmd_recv, 0, sizeof(cmd_recv));
689           cmd_recv.opcode[0] = DAYNA_CMD_RECV;
690           len = MAX_BYTES_RX + DSE_EXTRAS_RX;
691           _lto2b(len, &(cmd_recv.length[0]));
692           cmd_recv.byte6 = 0xC0;
693 
694           error = dse_scsipi_cmd(sc->sc_periph,
695               (void *)&cmd_recv, sizeof(cmd_recv),
696               sc->sc_rbuf, RBUF_LEN, DSE_RETRIES, DSE_TIMEOUT, NULL,
697               XS_CTL_NOSLEEP | XS_CTL_POLL | XS_CTL_DATA_IN);
698           if (error)
699                     callout_schedule(&sc->sc_recv_ch, dse_poll);
700 }
701 
702 
703 /*
704  * We copy the data into mbufs.  When full cluster sized units are present
705  * we copy into clusters.
706  */
707 static struct mbuf *
dse_get(struct dse_softc * sc,uint8_t * data,int totlen)708 dse_get(struct dse_softc *sc, uint8_t *data, int totlen)
709 {
710           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
711           struct mbuf *m, *m0, *newm;
712           int len;
713 
714           MGETHDR(m0, M_DONTWAIT, MT_DATA);
715           if (m0 == NULL)
716                     return NULL;
717 
718           m_set_rcvif(m0, ifp);
719           m0->m_pkthdr.len = totlen;
720           len       = MHLEN;
721           m = m0;
722 
723           while (totlen > 0) {
724                     if (totlen >= MINCLSIZE) {
725                               MCLGET(m, M_DONTWAIT);
726                               if((m->m_flags & M_EXT) == 0)
727                                         goto bad;
728 
729                               len = MCLBYTES;
730                     }
731 
732                     if (m == m0) {
733                               char *newdata = (char *)
734                                   ALIGN(m->m_data + sizeof(struct ether_header)) -
735                                   sizeof(struct ether_header);
736                               len -= newdata - m->m_data;
737                               m->m_data = newdata;
738                     }
739 
740                     m->m_len = len = uimin(totlen, len);
741                     memcpy(mtod(m, void *), data, len);
742                     data += len;
743 
744                     totlen -= len;
745                     if (totlen > 0) {
746                               MGET(newm, M_DONTWAIT, MT_DATA);
747                               if (newm == NULL)
748                                         goto bad;
749 
750                               len = MLEN;
751                               m = m->m_next = newm;
752                     }
753           }
754 
755           return m0;
756 
757 bad:
758           m_freem(m0);
759           return NULL ;
760 }
761 
762 
763 #ifdef MAC68K_DEBUG
764 static int
peek_packet(uint8_t * buf)765 peek_packet(uint8_t*  buf)
766 {
767           struct ether_header *eh;
768           uint16_t type;
769           int len;
770 
771           eh = (struct ether_header*)buf;
772           type = _2btol((uint8_t*)&(eh->ether_type));
773 
774           len = sizeof(struct ether_header);
775 
776           if (type <= ETHERMTU) {
777                     /* for 802.3 */
778                     len += type;
779           } else{
780                     /* for Ethernet II (DIX) */
781                     switch (type) {
782                       case ETHERTYPE_ARP:
783                               len += 28;
784                               break;
785                       case ETHERTYPE_IP:
786                               len += _2btol(buf + sizeof(struct ether_header) + 2);
787                               break;
788                       default:
789                               len = 0;
790                               goto l_end;
791                               break;
792                     }
793           }
794           if (len < DSE_MINSIZE) {
795                     len = DSE_MINSIZE;
796           }
797           len += ETHER_CRC_LEN;
798 
799   l_end:;
800           return len;
801 }
802 #endif
803 
804 
805 /*
806  * Pass packets to higher levels.
807  */
808 static int
dse_read(struct dse_softc * sc,uint8_t * data,int datalen)809 dse_read(struct dse_softc *sc, uint8_t *data, int datalen)
810 {
811           struct mbuf *m;
812           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
813           int       len;
814           int       n;
815 #ifdef MAC68K_DEBUG
816           int       peek_flag = 1;
817 #endif
818 
819           mutex_enter(&sc->sc_iflock);
820           n = 0;
821           while (datalen >= DSE_HEADER_RX) {
822                     /*
823                      * fetch bytes of stream.
824                      * here length = (ether frame length) + (FCS's 4 bytes)
825                      */
826                     /* fetch frame length */
827                     len = _2btol(data);
828 
829                     /* skip header part */
830                     data      += DSE_HEADER_RX;
831                     datalen -= DSE_HEADER_RX;
832 
833 #if 0     /* 03/10/2001  only for debug */
834                     {
835                               printf("DATALEN %d len %d\n", datalen, len);
836                               int       j;
837                               printf("\ndump[%d]: ",n);
838                               for ( j = 0 ; j < datalen ; j++ ) {
839                                         printf("%02X ",data[j-DSE_HEADER_RX]);
840                               }
841                     }
842 #endif
843 #ifdef MAC68K_DEBUG
844                     if (peek_flag) {
845                               peek_flag = 0;
846                               len = peek_packet(data);
847                     }
848 #endif
849                     if (len == 0)
850                               break;
851 
852 #ifdef DSE_DEBUG
853                     aprint_error_dev(sc->sc_dev, "dse_read: datalen = %d, packetlen"
854                         " = %d, proto = 0x%04x\n", datalen, len,
855                         ntohs(((struct ether_header *)data)->ether_type));
856 #endif
857                     if ((len < (DSE_MINSIZE + ETHER_CRC_LEN)) ||
858                          (MAX_BYTES_RX < len)) {
859 #ifdef DSE_DEBUG
860                               aprint_error_dev(sc->sc_dev, "invalid packet size "
861                                   "%d; dropping\n", len);
862 #endif
863                               if_statinc(ifp, if_ierrors);
864                               break;
865                     }
866 
867                     /* Don't need crc. Must keep ether header for BPF */
868                     m = dse_get(sc, data, len - ETHER_CRC_LEN);
869                     if (m == NULL) {
870 #ifdef DSE_DEBUG
871                               if (sc->sc_debug)
872                                         aprint_error_dev(sc->sc_dev, "dse_read: "
873                                             "dse_get returned null\n");
874 #endif
875                               if_statinc(ifp, if_ierrors);
876                               goto next_packet;
877                     }
878                     if_statinc(ifp, if_ipackets);
879 
880                     /*
881                      * Check if there's a BPF listener on this interface.
882                      * If so, hand off the raw packet to BPF.
883                      */
884                     if (ifp->if_bpf)
885                               bpf_mtap(ifp, m, BPF_D_OUT);
886 
887                     /* Pass the packet up. */
888                     if_percpuq_enqueue(sc->sc_ipq, m);
889 
890   next_packet:
891                     data      += len;
892                     datalen   -= len;
893                     n++;
894           }
895           mutex_exit(&sc->sc_iflock);
896 
897           return n;
898 }
899 
900 
901 static void
dsewatchdog(struct ifnet * ifp)902 dsewatchdog(struct ifnet *ifp)
903 {
904           struct dse_softc *sc = ifp->if_softc;
905 
906           log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
907           if_statinc(ifp, if_oerrors);
908 
909           dse_reset(sc);
910 }
911 
912 
913 static int
dse_reset(struct dse_softc * sc)914 dse_reset(struct dse_softc *sc)
915 {
916           int error;
917 #if 0
918           /* Maybe we don't *really* want to reset the entire bus
919            * because the ctron isn't working. We would like to send a
920            * "BUS DEVICE RESET" message, but don't think the ctron
921            * understands it.
922            */
923           error = dse_scsipi_cmd(sc->sc_periph, 0, 0, 0, 0, DSE_RETRIES, 2000,
924               NULL, XS_CTL_RESET);
925 #endif
926           error = dse_init(sc);
927           return error;
928 }
929 
930 
931 static int
dse_init_adaptor(struct dse_softc * sc)932 dse_init_adaptor(struct dse_softc *sc)
933 {
934           scsi_dayna_ether_generic cmd_vend1;
935           u_char tmpbuf[sizeof(cmd_vend1)];
936           int error;
937 
938 #if 0     /* 07/21/2001 for test */
939           /* Maybe we don't *really* want to reset the entire bus
940            * because the ctron isn't working. We would like to send a
941            * "BUS DEVICE RESET" message, but don't think the ctron
942            * understands it.
943            */
944           error = dse_scsipi_cmd(sc->sc_periph, 0, 0, 0, 0, DSE_RETRIES,
945               2000, NULL, XS_CTL_RESET);
946 #endif
947 
948           cmd_vend1 = sonic_ether_vendor1;
949 
950           error = dse_scsipi_cmd(sc->sc_periph,
951               (struct scsipi_generic *)&cmd_vend1, sizeof(cmd_vend1),
952                     &(tmpbuf[0]), sizeof(tmpbuf),
953               DSE_RETRIES, DSE_TIMEOUT, NULL, XS_CTL_POLL | XS_CTL_DATA_IN);
954 
955           if (error)
956                     goto l_end;
957 
958           /* wait 500 msec */
959           kpause("dsesleep", false, hz / 2, NULL);
960 
961 l_end:
962           return error;
963 }
964 
965 
966 static int
dse_get_addr(struct dse_softc * sc,uint8_t * myaddr)967 dse_get_addr(struct dse_softc *sc, uint8_t *myaddr)
968 {
969           scsi_dayna_ether_generic cmd_get_addr;
970           u_char tmpbuf[REQ_LEN_GET_ADDR];
971           int error;
972 
973           memset(&cmd_get_addr, 0, sizeof(cmd_get_addr));
974           cmd_get_addr.opcode[0] = DAYNA_CMD_GET_ADDR;
975           _lto2b(REQ_LEN_GET_ADDR, cmd_get_addr.length);
976 
977           error = dse_scsipi_cmd(sc->sc_periph,
978               (struct scsipi_generic *)&cmd_get_addr, sizeof(cmd_get_addr),
979               tmpbuf, sizeof(tmpbuf),
980               DSE_RETRIES, DSE_TIMEOUT, NULL, XS_CTL_POLL | XS_CTL_DATA_IN);
981 
982           if (error == 0) {
983                     memcpy(myaddr, &(tmpbuf[0]), ETHER_ADDR_LEN);
984 
985                     aprint_normal_dev(sc->sc_dev, "ethernet address %s\n",
986                                  ether_sprintf(myaddr));
987           }
988 
989           return error;
990 }
991 
992 
993 #if 0     /* 07/16/2000 comment-out */
994 static int
995 dse_set_mode(struct dse_softc *sc, int len, int mode)
996 
997           return 0;
998 }
999 #endif
1000 
1001 
1002 static int
dse_init(struct dse_softc * sc)1003 dse_init(struct dse_softc *sc)
1004 {
1005           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1006           int error = 0;
1007 
1008           if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == IFF_UP) {
1009                     ifp->if_flags |= IFF_RUNNING;
1010                     mutex_enter(&sc->sc_iflock);
1011                     if (!sc->sc_recv_work_pending)  {
1012                               sc->sc_recv_work_pending = true;
1013                               workqueue_enqueue(sc->sc_recv_wq, &sc->sc_recv_work,
1014                                   NULL);
1015                     }
1016                     mutex_exit(&sc->sc_iflock);
1017                     ifp->if_flags &= ~IFF_OACTIVE;
1018                     mutex_enter(&sc->sc_iflock);
1019                     if (!sc->sc_send_work_pending)  {
1020                               sc->sc_send_work_pending = true;
1021                               workqueue_enqueue(sc->sc_send_wq, &sc->sc_send_work,
1022                                   NULL);
1023                     }
1024                     mutex_exit(&sc->sc_iflock);
1025           }
1026           return error;
1027 }
1028 
1029 
1030 static uint8_t      BROADCAST_ADDR[ETHER_ADDR_LEN] =
1031                               { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
1032 
1033 
1034 static int
dse_set_multi(struct dse_softc * sc)1035 dse_set_multi(struct dse_softc *sc)
1036 {
1037           scsi_dayna_ether_generic cmd_set_multi;
1038           struct ether_multistep step;
1039           struct ether_multi *enm;
1040           u_char *cp, *mybuf;
1041           int error, len;
1042 
1043           error = 0;
1044 
1045 #ifdef DSE_DEBUG
1046           aprint_error_dev(sc->sc_dev, "dse_set_multi\n");
1047 #endif
1048 
1049           mybuf = malloc(ETHER_ADDR_LEN * DSE_MCAST_MAX, M_DEVBUF, M_NOWAIT);
1050           if (mybuf == NULL) {
1051                     error = EIO;
1052                     goto l_end;
1053           }
1054 
1055           /*
1056            * copy all entries to transfer buffer
1057            */
1058           cp = mybuf;
1059           len = 0;
1060           ETHER_FIRST_MULTI(step, &(sc->sc_ethercom), enm);
1061           while ((len < (DSE_MCAST_MAX - 1)) && (enm != NULL)) {
1062                     /* ### refer low side entry */
1063                     memcpy(cp, enm->enm_addrlo, ETHER_ADDR_LEN);
1064 
1065                     cp += ETHER_ADDR_LEN;
1066                     len++;
1067                     ETHER_NEXT_MULTI(step, enm);
1068           }
1069 
1070           /* add broadcast address as default */
1071           memcpy(cp, BROADCAST_ADDR, ETHER_ADDR_LEN);
1072           len++;
1073 
1074           len *= ETHER_ADDR_LEN;
1075 
1076           memset(&cmd_set_multi, 0, sizeof(cmd_set_multi));
1077           cmd_set_multi.opcode[0] = DAYNA_CMD_SET_MULTI;
1078           _lto2b(len, cmd_set_multi.length);
1079 
1080           error = dse_scsipi_cmd(sc->sc_periph,
1081               (struct scsipi_generic*)&cmd_set_multi, sizeof(cmd_set_multi),
1082               mybuf, len, DSE_RETRIES, DSE_TIMEOUT, NULL, XS_CTL_DATA_OUT);
1083 
1084           free(mybuf, M_DEVBUF);
1085 
1086 l_end:
1087           return error;
1088 }
1089 
1090 
1091 static void
dse_stop(struct dse_softc * sc)1092 dse_stop(struct dse_softc *sc)
1093 {
1094           /* Don't schedule any reads */
1095           callout_stop(&sc->sc_recv_ch);
1096 
1097           /* Wait for the workqueues to finish */
1098           mutex_enter(&sc->sc_iflock);
1099           workqueue_wait(sc->sc_recv_wq, &sc->sc_recv_work);
1100           workqueue_wait(sc->sc_send_wq, &sc->sc_send_work);
1101           mutex_exit(&sc->sc_iflock);
1102 
1103           /* Abort any scsi cmds in progress */
1104           mutex_enter(chan_mtx(sc->sc_periph->periph_channel));
1105           scsipi_kill_pending(sc->sc_periph);
1106           mutex_exit(chan_mtx(sc->sc_periph->periph_channel));
1107 }
1108 
1109 
1110 /*
1111  * Process an ioctl request.
1112  */
1113 static int
dse_ioctl(struct ifnet * ifp,u_long cmd,void * data)1114 dse_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1115 {
1116           struct dse_softc *sc;
1117           struct ifaddr *ifa;
1118           struct ifreq *ifr;
1119           struct sockaddr *sa;
1120           int error;
1121 
1122           error = 0;
1123           sc = ifp->if_softc;
1124           ifa = (struct ifaddr *)data;
1125           ifr = (struct ifreq *)data;
1126 
1127           switch (cmd) {
1128           case SIOCINITIFADDR:
1129                     mutex_enter(&sc->sc_iflock);
1130                     if ((error = dse_enable(sc)) != 0)
1131                               break;
1132                     ifp->if_flags |= IFF_UP;
1133                     mutex_exit(&sc->sc_iflock);
1134 
1135 #if 0
1136                     if ((error = dse_set_media(sc, CMEDIA_AUTOSENSE)) != 0)
1137                               break;
1138 #endif
1139 
1140                     switch (ifa->ifa_addr->sa_family) {
1141 #ifdef INET
1142                     case AF_INET:
1143                               if ((error = dse_init(sc)) != 0)
1144                                         break;
1145                               arp_ifinit(ifp, ifa);
1146                               break;
1147 #endif
1148 #ifdef NETATALK
1149                     case AF_APPLETALK:
1150                               if ((error = dse_init(sc)) != 0)
1151                                         break;
1152                               break;
1153 #endif
1154                     default:
1155                               error = dse_init(sc);
1156                               break;
1157                     }
1158                     break;
1159 
1160 
1161           case SIOCSIFADDR:
1162                     mutex_enter(&sc->sc_iflock);
1163                     error = dse_enable(sc);
1164                     mutex_exit(&sc->sc_iflock);
1165                     if (error != 0)
1166                               break;
1167                     ifp->if_flags |= IFF_UP;
1168 
1169                     switch (ifa->ifa_addr->sa_family) {
1170 #ifdef INET
1171                     case AF_INET:
1172                               if ((error = dse_init(sc)) != 0)
1173                                         break;
1174                               arp_ifinit(ifp, ifa);
1175                               break;
1176 #endif
1177 #ifdef NETATALK
1178                     case AF_APPLETALK:
1179                               if ((error = dse_init(sc)) != 0)
1180                                         break;
1181                               break;
1182 #endif
1183                     default:
1184                               error = dse_init(sc);
1185                               break;
1186                     }
1187                     break;
1188 
1189           case SIOCSIFFLAGS:
1190                     if ((error = ifioctl_common(ifp, cmd, data)) != 0)
1191                               break;
1192                     /* XXX re-use ether_ioctl() */
1193                     switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
1194                     case IFF_RUNNING:
1195                               /*
1196                                * If interface is marked down and it is running, then
1197                                * stop it.
1198                                */
1199                               dse_stop(sc);
1200                               mutex_enter(&sc->sc_iflock);
1201                               ifp->if_flags &= ~IFF_RUNNING;
1202                               dse_disable(sc);
1203                               mutex_exit(&sc->sc_iflock);
1204                               break;
1205                     case IFF_UP:
1206                               /*
1207                                * If interface is marked up and it is stopped, then
1208                                * start it.
1209                                */
1210                               mutex_enter(&sc->sc_iflock);
1211                               error = dse_enable(sc);
1212                               mutex_exit(&sc->sc_iflock);
1213                               if (error)
1214                                         break;
1215                               error = dse_init(sc);
1216                               break;
1217                     default:
1218                               /*
1219                                * Reset the interface to pick up changes in any other
1220                                * flags that affect hardware registers.
1221                                */
1222                               mutex_enter(&sc->sc_iflock);
1223                               if (sc->sc_enabled)
1224                                         error = dse_init(sc);
1225                               mutex_exit(&sc->sc_iflock);
1226                               break;
1227                     }
1228 #ifdef DSE_DEBUG
1229                     if (ifp->if_flags & IFF_DEBUG)
1230                               sc->sc_debug = 1;
1231                     else
1232                               sc->sc_debug = 0;
1233 #endif
1234                     break;
1235 
1236           case SIOCADDMULTI:
1237                     if (sc->sc_enabled == 0) {
1238                               error = EIO;
1239                               break;
1240                     }
1241                     mutex_enter(&sc->sc_iflock);
1242                     sa = sockaddr_dup(ifreq_getaddr(cmd, ifr), M_WAITOK);
1243                     mutex_exit(&sc->sc_iflock);
1244                     if (ether_addmulti(sa, &sc->sc_ethercom) == ENETRESET) {
1245                               error = dse_set_multi(sc);
1246 #ifdef DSE_DEBUG
1247                               aprint_error_dev(sc->sc_dev, "add multi: %s\n",
1248                                            ether_sprintf(ifr->ifr_addr.sa_data));
1249 #endif
1250                     } else
1251                               error = 0;
1252 
1253                     mutex_enter(&sc->sc_iflock);
1254                     sockaddr_free(sa);
1255                     mutex_exit(&sc->sc_iflock);
1256 
1257                     break;
1258 
1259           case SIOCDELMULTI:
1260                     if (sc->sc_enabled == 0) {
1261                               error = EIO;
1262                               break;
1263                     }
1264                     mutex_enter(&sc->sc_iflock);
1265                     sa = sockaddr_dup(ifreq_getaddr(cmd, ifr), M_WAITOK);
1266                     mutex_exit(&sc->sc_iflock);
1267                     if (ether_delmulti(sa, &sc->sc_ethercom) == ENETRESET) {
1268                               error = dse_set_multi(sc);
1269 #ifdef DSE_DEBUG
1270                               aprint_error_dev(sc->sc_dev, "delete multi: %s\n",
1271                                   ether_sprintf(ifr->ifr_addr.sa_data));
1272 #endif
1273                     } else
1274                               error = 0;
1275 
1276                     mutex_enter(&sc->sc_iflock);
1277                     sockaddr_free(sa);
1278                     mutex_exit(&sc->sc_iflock);
1279 
1280                     break;
1281 
1282           default:
1283                     error = ether_ioctl(ifp, cmd, data);
1284                     break;
1285           }
1286 
1287 
1288           return error;
1289 }
1290 
1291 
1292 /*
1293  * Enable the network interface.
1294  */
1295 int
dse_enable(struct dse_softc * sc)1296 dse_enable(struct dse_softc *sc)
1297 {
1298           struct scsipi_periph *periph = sc->sc_periph;
1299           struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
1300           int error = 0;
1301 
1302           if (sc->sc_enabled == 0) {
1303                     if ((error = scsipi_adapter_addref(adapt)) == 0)
1304                               sc->sc_enabled = 1;
1305                     else
1306                               aprint_error_dev(sc->sc_dev, "device enable failed\n");
1307           }
1308 
1309           return error;
1310 }
1311 
1312 
1313 /*
1314  * Disable the network interface.
1315  */
1316 void
dse_disable(struct dse_softc * sc)1317 dse_disable(struct dse_softc *sc)
1318 {
1319           struct scsipi_periph *periph = sc->sc_periph;
1320           struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
1321           if (sc->sc_enabled != 0) {
1322                     scsipi_adapter_delref(adapt);
1323                     sc->sc_enabled = 0;
1324           }
1325 }
1326 
1327 
1328 #define   DSEUNIT(z)          (minor(z))
1329 
1330 /*
1331  * open the device.
1332  */
1333 int
dseopen(dev_t dev,int flag,int fmt,struct lwp * l)1334 dseopen(dev_t dev, int flag, int fmt, struct lwp *l)
1335 {
1336           int unit, error;
1337           struct dse_softc *sc;
1338           struct scsipi_periph *periph;
1339           struct scsipi_adapter *adapt;
1340 
1341           unit = DSEUNIT(dev);
1342           sc = device_lookup_private(&dse_cd, unit);
1343           if (sc == NULL)
1344                     return ENXIO;
1345 
1346           periph = sc->sc_periph;
1347           adapt = periph->periph_channel->chan_adapter;
1348 
1349           if ((error = scsipi_adapter_addref(adapt)) != 0)
1350                     return error;
1351 
1352           SC_DEBUG(periph, SCSIPI_DB1,
1353               ("scopen: dev=0x%"PRIx64" (unit %d (of %d))\n", dev, unit,
1354               dse_cd.cd_ndevs));
1355 
1356           periph->periph_flags |= PERIPH_OPEN;
1357 
1358           SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
1359 
1360           return 0;
1361 }
1362 
1363 
1364 /*
1365  * close the device.. only called if we are the LAST
1366  * occurrence of an open device
1367  */
1368 int
dseclose(dev_t dev,int flag,int fmt,struct lwp * l)1369 dseclose(dev_t dev, int flag, int fmt, struct lwp *l)
1370 {
1371           struct dse_softc *sc = device_lookup_private(&dse_cd, DSEUNIT(dev));
1372           struct scsipi_periph *periph = sc->sc_periph;
1373           struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
1374 
1375           SC_DEBUG(sc->sc_periph, SCSIPI_DB1, ("closing\n"));
1376 
1377           scsipi_wait_drain(periph);
1378 
1379           scsipi_adapter_delref(adapt);
1380           periph->periph_flags &= ~PERIPH_OPEN;
1381 
1382           return 0;
1383 }
1384 
1385 
1386 /*
1387  * Perform special action on behalf of the user
1388  * Only does generic scsi ioctls.
1389  */
1390 int
dseioctl(dev_t dev,u_long cmd,void * addr,int flag,struct lwp * l)1391 dseioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
1392 {
1393           struct dse_softc *sc = device_lookup_private(&dse_cd, DSEUNIT(dev));
1394 
1395           return (scsipi_do_ioctl(sc->sc_periph, dev, cmd, addr, flag, l));
1396 }
1397 
1398