Merge from vendor branch GCC:
[dragonfly.git] / sys / dev / atm / hfa / fore_stats.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/dev/hfa/fore_stats.c,v 1.4 1999/08/28 00:41:52 peter Exp $
27  *      @(#) $DragonFly: src/sys/dev/atm/hfa/fore_stats.c,v 1.5 2003/08/07 21:16:49 dillon Exp $
28  */
29
30 /*
31  * FORE Systems 200-Series Adapter Support
32  * ---------------------------------------
33  *
34  * Device statistics routines
35  *
36  */
37
38 #include "fore_include.h"
39
40 /*
41  * Get device statistics from CP
42  * 
43  * This function will issue a GET_STATS command to the CP in order to
44  * initiate the DMA transfer of the CP's statistics structure to the host.
45  * We will then sleep pending command completion.  This must only be called
46  * from the ioctl system call handler.
47  *
48  * Called at splnet.
49  *
50  * Arguments:
51  *      fup     pointer to device unit structure
52  *
53  * Returns:
54  *      0       stats retrieval successful
55  *      errno   stats retrieval failed - reason indicated
56  *
57  */
58 int
59 fore_get_stats(fup)
60         Fore_unit       *fup;
61 {
62         H_cmd_queue     *hcp;
63         Cmd_queue       *cqp;
64         int             s, sst;
65
66         ATM_DEBUG1("fore_get_stats: fup=%p\n", fup);
67
68         /*
69          * Make sure device has been initialized
70          */
71         if ((fup->fu_flags & CUF_INITED) == 0) {
72                 return (EIO);
73         }
74
75         /*
76          * If someone has already initiated a stats request, we'll
77          * just wait for that one to complete
78          */
79         s = splimp();
80         if (fup->fu_flags & FUF_STATCMD) {
81
82 #if (defined(BSD) && (BSD >= 199103))
83                 sst = tsleep((caddr_t)&fup->fu_stats, PCATCH, "fore", 0);
84 #else
85                 sst = sleep((caddr_t)&fup->fu_stats, PCATCH);
86                 if (sst != 0)
87                         sst = EINTR;
88 #endif
89                 (void) splx(s);
90                 return (sst ? sst : fup->fu_stats_ret);
91         }
92
93         /*
94          * Limit stats gathering to once a second or so
95          */
96         if (time_second == fup->fu_stats_time) {
97                 (void) splx(s);
98                 return (0);
99         } else
100                 fup->fu_stats_time = time_second;
101
102         /*
103          * Queue command at end of command queue
104          */
105         hcp = fup->fu_cmd_tail;
106         if ((*hcp->hcq_status) & QSTAT_FREE) {
107                 void    *dma;
108
109                 /*
110                  * Queue entry available, so set our view of things up
111                  */
112                 hcp->hcq_code = CMD_GET_STATS;
113                 hcp->hcq_arg = NULL;
114                 fup->fu_cmd_tail = hcp->hcq_next;
115
116                 /*
117                  * Now set the CP-resident queue entry - the CP will grab
118                  * the command when the op-code is set.
119                  */
120                 cqp = hcp->hcq_cpelem;
121                 (*hcp->hcq_status) = QSTAT_PENDING;
122
123                 dma = DMA_GET_ADDR(fup->fu_stats, sizeof(Fore_cp_stats),
124                         FORE_STATS_ALIGN, 0);
125                 if (dma == NULL) {
126                         fup->fu_stats->st_drv.drv_cm_nodma++;
127                         (void) splx(s);
128                         return (EIO);
129                 }
130                 fup->fu_statsd = dma;
131                 cqp->cmdq_stats.stats_buffer = (CP_dma) CP_WRITE(dma);
132
133                 fup->fu_flags |= FUF_STATCMD;
134                 cqp->cmdq_stats.stats_cmd = 
135                         CP_WRITE(CMD_GET_STATS | CMD_INTR_REQ);
136
137                 /*
138                  * Now wait for command to finish
139                  */
140 #if (defined(BSD) && (BSD >= 199103))
141                 sst = tsleep((caddr_t)&fup->fu_stats, PCATCH, "fore", 0);
142 #else
143                 sst = sleep((caddr_t)&fup->fu_stats, PCATCH);
144                 if (sst != 0)
145                         sst = EINTR;
146 #endif
147                 (void) splx(s);
148                 return (sst ? sst : fup->fu_stats_ret);
149
150         } else {
151                 /*
152                  * Command queue full
153                  */
154                 fup->fu_stats->st_drv.drv_cm_full++;
155                 (void) splx(s);
156                 return (EIO);
157         }
158 }
159